Skip to main content

yii change sorting sort order by drag drop Creating a jQueryUI Sortable CGridView Yii Framework


The article below is copied from this URL http://www.yiiframework.com/wiki/238/creating-a-jqueryui-sortable-cgridview/ . That linked article has a small error which i have removed here:
----------------------------------------------------------------------------------------
I have had to do this a couple of times now so I figured I would share it with the community. I am going to keep this short because I really hope that you are familiar with jQueryUI's Sortable class before starting this tutorial.
Here are the basic steps to achieve this:
  1. Make sure your database table has a 'sortOrder' field.
  2. (Optional) Add the 'sortOrder' field to your Rules() function in your model
  3. Add the 'actionSort()' method to your controller to apply the sorting via ajax
  4. Add jQuery UI to your view that has the CGridView
  5. Setup the jQuery UI Code to work with the CGridView in question
  6. (Optional) Apply the sorting to your model's search() function if need be
So lets get started!
Step 1 is self-explanatory, just make sure that you have an INT field in your database to store the sortOrder of each item ( for this article we will call this field 'sortOrder' )
Step 2: This step is optional but recommended. Add this line to the model who's items you are sorting.
array('sortOrder', 'numerical', 'integerOnly'=>true),
Step 3: This is the part where we add the code to a controller that will apply the new sorting order to the rows in your database. Note I will be using a controller titled 'Project'. You will see me link to this controller in the jQueryUI Sortable javascript code.
  • Note: Please make sure that the user who will be doing the sorting has access to this action in your 'accessRules()' for the controller in question.
'Project' is the model that I am applying the ordering to. You can add a CDbCriteria in here if you need to sort just specific rows.
public function actionSort()
{
    if (isset($_POST['items']) && is_array($_POST['items'])) {
        $i = 0;
        foreach ($_POST['items'] as $item) {
            $project = Project::model()->findByPk($item);
            $project->sortOrder = $i;
            $project->saveAttributes($project);
            $i++;
        }
    }
}
Step 4: OK Here is the fun part. We need to setup jQuery UI to link to the CGridView w/o having to modify the source of the CGridView in any way. By doing this we don't have to modify any of the core files or extend CGridView in any way.
<?php
    $str_js = "
        var fixHelper = function(e, ui) {
            ui.children().each(function() {
                $(this).width($(this).width());
            });
            return ui;
        };
 
        $('#project-grid table.items tbody').sortable({
            forcePlaceholderSize: true,
            forceHelperSize: true,
            items: 'tr',
            update : function () {
                serial = $('#project-grid table.items tbody').sortable('serialize', {key: 'items[]', attribute: 'class'});
                $.ajax({
                    'url': '" . $this->createUrl('//project/sort') . "',
                    'type': 'post',
                    'data': serial,
                    'success': function(data){
                    },
                    'error': function(request, status, error){
                        alert('We are unable to set the sort order at this time.  Please try again in a few minutes.');
                    }
                });
            },
            helper: fixHelper
        }).disableSelection();
    ";
 
    Yii::app()->clientScript->registerScript('sortable-project', $str_js);
?>
<?php $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'project-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'rowCssClassExpression'=>'"items[]_{$data->id}"',
    'columns'=>array(
        'id',
        'title',
        'categoryId',
        'sortOrder',
        array(
            'class'=>'CButtonColumn',
        ),
    ),
)); ?>
OK So first off we are setting up the jQueryUI Sortable object in javascript and attaching it to our CGridView. Things to note are: 'project-grid' is the 'id' of our CGridView and will need to be switched to the ID of your CGridView. Also, the following line will need to be altered to point to your //controller/action path where you added the 'actionSort()' function:
'url': '" . $this->createUrl('//project/sort') . "',
Once the javascript is setup we need to setup the CGridView. The only two things out of the ordinary are that we are explicitly setting the 'id' of the CGridView and we are also setting the 'rowCssClassExpression' variable to work with jQueryUI Sortable.
'id'=>'project-grid',
'rowCssClassExpression'=>'"items[]_{$data->id}"',
Step 5: In your view file or controller that is displaying the CGridView you will need to tell Yii to add jQueryUI to your page.
Yii::app()->clientScript->registerScriptFile('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js');
Step 6: If you are planning on using your model::Search() function to setup DataProviders for things like CListView and CGridView I recommend you add the following line to the Search() function towards the bottom before the CActiveDataProvider is created:
$criteria->order = 'sortOrder ASC';
I hope this helps some people out! If you are having any problems please go through this write-up again to make sure you didn't miss anything.

Popular posts from this blog

Yii, return to previous url after login or logout

If you want to return to your previous url after login or logout try this : <?php $this -> redirect (Yii :: app () -> request -> urlReferrer ); ?> To set the return url to be the url that was before the login page or registeration page was called you can put following code in views/layouts/main.php file : <?php //this checks id the controller action is not 'login' then it keeps the current url in returnUrl if (CController :: getAction () -> id != 'login' ) { Yii :: app () -> user -> setReturnUrl (Yii :: app () -> request -> getUrl ()); } ?>

Yii2: Using csrf token

Yii2: Using csrf token First, if you do not understand what is the CSRF token? and why should we use it, please refer to the following link : https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) One of the new features of Yii2 is CSRF validation enabled by default. If you use ajax or basic form as follows : <form action='#' method='POST'> ........... </form> You will get an error exception : Bad Request (#400): Unable to verify your data submission That is because you do not submit csrf token. The easiest way if you dont care about csrf just disable it in main config : 'components' => [ 'request' => [ .... 'enableCsrfValidation'=>false, ], ..... ], Or in Controller : public function beforeAction($action) { $this->enableCsrfValidation = false; return parent::beforeAction($action); } So how to use Csrf Validation for your strong security website: * Wi