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
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 ^-^
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!
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...
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.
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.
order is not getting saved in database
I did what ever is mentioned above but when i drag and drop records the order of records is not getting saved its refreshing back to its original order.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.