This works by fetching all the records (ordered by their current sort_order value, apart from the one being updated) and re-assigning their sort_order value starting from 1. We of course already specify the sort_order of the record we are updating so that one does not need re-assigning.
This works well in situations where records get deleted - the sort order of all records get updated when you re-order any of the records.
Controller:
public function actionOrder()
{
$model=$this->loadModel();
if(!empty($_GET['dir']) && ($_GET['dir']=='up' || $_GET['dir']=='down'))
{
if($_GET['dir']=='up')
{
$model->sort_order=$model->sort_order-1;
}
elseif($_GET['dir']=='down')
{
$model->sort_order=$model->sort_order+1;
}
// we don't need to update the current record with a new sort order value
$vehicles=Vehicle::model()->findAll(array('condition'=>'id !='.$model->id, 'order'=>'sort_order'));
if($model->sort_order != 0 && $model->sort_order <= count($vehicles)+1)
{
$model->update();
$i=1;
foreach($vehicles as $vehicle)
{
if($i != $model->sort_order) // skip the record that holds the requested sort order value
{
$vehicle->sort_order=$i; // assign new sort orders to these records
}
else
{
$vehicle->sort_order=$i+1; // add one to the sort order value of the record that holds the requested sort order value
$i++; // because we have already assigned the next sort_order value above
}
$vehicle->update();
$i++;
}
}
}
else
{
$this->redirect(array('admin'));
}
}
CGridView Column:
array(
'name'=>'sort_order',
'type'=>'raw',
'value'=>'$data->SortOrder',
),
public function getSortOrder()
{
$output = sprintf("%02d", $this->sort_order);
$output.= " [".CHtml::link('up', array('order', 'id'=>$this->id, 'dir'=>'up'), array('class'=>'ajaxupdate'))."]";
$output.= " [".CHtml::link('down', array('order', 'id'=>$this->id, 'dir'=>'down'), array('class'=>'ajaxupdate'))."]";
return $output;
}
JS function:
Yii::app()->clientScript->registerScript('ajaxupdate', "
$('#vehicle-grid a.ajaxupdate').live('click', function() {
$.fn.yiiGridView.update('vehicle-grid', {
type: 'POST',
url: $(this).attr('href'),
success: function() {
$.fn.yiiGridView.update('vehicle-grid');
}
});
return false;
});
");
A few questions:
-
Any potential flaws in this approach?
-
Any suggestions on improving the code?
-
Is it possible for the record that is being re-ordered to be highlighted once the change is made? So the user can see clearly that it has moved.