CGridView - re-ordering records

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:

  1. Any potential flaws in this approach?

  2. Any suggestions on improving the code?

  3. 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.

Hi GSTAR,

Many thanks …

Works great!

I’ve just have had to add $id here:


	

public function actionOrder($id)

	{

		$model=$this->loadModel($id);



Any suggestions anyone?