Yii 1.1: yiisortablemodel

Set of tools to help keeping records of a model manually sorted. Include sortables CGridView, CListView and CActiveRecord.
13 followers

Yii Sortable Model

Overview

Yii Sortable Model is a Yii extension that provides with a set of tools to help keeping records of a model manually sorted. Each of these tools can be used alone. Specifically, it provides with:

SortableCGridView

CGridView widget extended to allow drag and drop sorting of records. With it, users will be able to drag and drop with the mouse the rows of the grid to change records order. New order will be automatically saved in the database through an Ajax call.

SortableCListView

CListView widget extended to list records sorted.

SortableCActiveRecord

CActiveRecord extended to keep records order consistent when adding or deleting items. With it, when a new record is added it will get automatically the last position, and when one is deleted the rest of records will be rearranged to fill its gap.

SortableCActiveRecordBehavior

Provides the same functionality than SortableCActiveRecord through a behavior, to allow using custom classes as models.

Requirements

Yii Sortable Model has been tested with Yii v1.1.8, but surely works with previous versions.

Setup

Download Yii Sortable Model from https://github.com/laMarciana/yiisortablemodel

Extract its contents to protected/extensions/ in your Yii installation.

Create a field in the database table of your model with an integer field. This field will be the responsable to store records order.

SortableCGridView

In your view, add:

<?php $this->widget('ext.yiisortablemodel.widgets.SortableCGridView', array(
  'dataProvider' => $dataProvider,
  'orderField' => 'order',
  'idField' => 'id',
  'orderUrl' => 'order',
); ?>

As in its parent, CGridView, you must provide a data provider, but in SortableCGridView this must be an instance of CActiveDataProvider (the standard if you are working from data coming from a model, like the ones generated by gii).

orderField property defines which is the field that it is meant to store the records order.

orderId property defines which is the field that it is meant to store the primary key of the record.

orderUrl property defines the name of the action that the controller from where the widget is called will use to trigger the actual ajax sorting. This must be configured as well in the actions() method of the controller. For example, if orderUrl is set to order, then in your controller you must have:

public function actions()
{
  return array(
    'order' => array(
       'class' => 'ext.yiisortablemodel.actions.AjaxSortingAction',
    ),
  );
}

Don't forget to update, if needed, the access rules to consider this new action. For example:

public function accessRules()
{
  return array(
     ...
     array('allow', 'actions' => array('order'), 'users' => array('@')),
     ...
  );
}

Look at the class reference for additional options.

SortableCListView

In your view, add:

<?php $this->widget('ext.yiisortablemodel.widgets.SortableCListView', array(
  'dataProvider' => $dataProvider,
  'orderField' => 'order',
); ?>

As in its parent, CListView, you must provide a data provider, but in SortableCListView this must be an instance of CActiveDataProvider (the standard if you are working from data coming from a model, like the ones generated by gii).

orderField property defines which is the field that it is meant to store records order.

Look at the class reference for additional options.

SortableCActiveRecord

First, add the models directory of this extension to the import option of the main configuration file (located in protected/config/main.php):

'import' => array(
  ...
  'ext.yiisortablemodel.models.*',
  ...
),

Tell your model to extend SortableCActiveRecord instead of CActiveRecord, and set its $orderField property to the field in the database table that stores records order:

class myModel extends SortableCActiveRecord {
  public $orderField = 'order';
  ...

SortableCActiveRecordBehavior

First, add the behaviors directory of this extension to the import option of the main configuration file (located in protected/config/main.php):

'import' => array(
  ...
  'ext.yiisortablemodel.behaviors.*',
  ...
),

Attach the behavior to your model, for example in the init() method, and set its $orderField property to the field in the database table that stores records order:

public function init()
{
   $this->attachBehavior('sortableModel', array(
      'class' => 'SortableCActiveRecordBehavior',
      'orderField' => 'order'
   ));
   parent::init();
}

Class Reference

You have a complete Class Reference, with all the additional options you can set up, in the doc folder. Class Reference generated by YiiDocumentor.

Resources

License

Copyright 2012, Marc Busqué Pérez, under GNU LESSER GENERAL PUBLIC LICENSE marc@lamarciana.com - http://www.lamarciana.com

Total 5 comments

#9248 report it
natb19 at 2012/07/31 11:42am
Great work!

Thanks @cram1010 for that, I'll have a play when I get a chance :)

One thing though... for people wanting to use this on data that are stored in groups (one to many rels etc, other types of grouping records) make sure that you have your default scope set correctly, as this component won't recognise you grouping/parent relationships unless you do (so the sort orders will get messy). Please lookup CActiveRecord.defaultScope() to understand what I mean.

#9246 report it
Marc Busque at 2012/07/31 11:04am
Version 1.1 - Added behavior

Ok, finally I had the time and I added SortableCActiveRecordBehavior as @yiqing95 suggested. As well, as @natb19 suggested, it's better keeping both options for different people needs.

Look at the updated documentation to know how to use it.

Thank your for your suggestions.

#9088 report it
natb19 at 2012/07/18 08:12pm
Re: good works , one suggestion

I suggest having both. Having a base class is useful for some people, but also having as a behaviour keeps things flexible...

#8869 report it
Marc Busque at 2012/07/05 04:32am
Re: good works , one suggestion

I think it is a good suggestion. I would look at this as soon as I have the time. Anyway, if you have the time to implement and test it feel free to send a pull request at https://github.com/laMarciana/yiiSortableModel.

Thank you!

#8862 report it
yiqing95 at 2012/07/04 09:52pm
good works , one suggestion

for the SortableCActiveRecord : in projects we often have our own base ActiveRecord . because the php is single root inheritance . so it's better implements the functionality as a behavior (not difficult )

class SortableArBehavior extends CActiveRecordBehavior
{
 
   public $orderField = 'order';
 
 
   protected function beforeSave()
   {
      $model = $this->getOwner();
      if ($model->isNewRecord) {
         $model2 = call_user_func(array(get_class($model), 'model'));
         $last_record = $model2->find(array(
            'order' => '`'.$this->orderField.'` DESC',
            'limit' => 1
         ));
         if ($last_record) {
            $model->{$this->orderField} = $last_record->{$this->orderField} + 1;
         } else {
            $model->{$this->orderField} = 1;
         }
      }
 
   } 
 
   protected function afterDelete()
   {
      $model= $this->getOwner();
      $model2 = call_user_func(array(get_class($model), 'model'));
      $following_records = $model2->findAll(array(
         'order' => '`'.$this->orderField.'` ASC',
         'condition' => '`'.$this->orderField.'` > '.$model->{$this->orderField},
      ));
      foreach ($following_records as $record) {
         $record->{$this->orderField}--;
         $record->update();
      }
   }
}

haven't test , just a thought ^-^

Leave a comment

Please to leave your comment.

Create extension