edatatables

DataTables grid widget with CGridView API.
21 followers

Goal of this widget/wrapper is to provide a drop in replacement for base CGridView widget from the Yii framework, using DataTables plugin.

It's usable, but in an early stage and needs some refurbishing. Please post issues on project's page.

Features

  • Redrawing of table contents (after paging/sorting/searching) using AJAX calls.
  • Using CGridView columns definition format, supports all basic special columns like Buttons, Checkbox, etc.
  • Partial editable cells support.
  • Custom buttons in table header.
  • Smoothness theme from JUI by default

It will be gradually enhanced to support more of DataTables features.

Requirements

Yii 1.1.8 or above.

Changes

0.8.5

  • bootstrap theme, enabled with 'bootstrap' attribute
  • fixed setting default sorting, use an array for $sort->defaultOrder
  • fixed fixed width of first column when selectableRows is set
  • fixed restoring the state from cookie when 'bStateSave' is used

0.8.3

  • fixed styles, by default jquery UI smoothness themeroller style is applied
  • fixed some JS code, all should work for now
  • by default, left only the refresh button in the toolbar located in the table header
  • updated the polish localization files to use » and › html entities, to be used as a template
  • started documenting features on the [wiki] (http://code.google.com/p/edatatables/w/list)

0.8.2

  • i18n support
  • fixed a but in the getFormattedData method, used to get data for ajax response
  • updated DataTables to 1.9.0

Usage

It's not 100% compatible with CGridView. I've decided not to alter the GET parameter names used by DataTables, so you have to use the provided EDTSort and EDTPagination classes as well as alter filter processing. See below.

Installation

Extract into extensions dir.

Import in config/main.php

'import' => array(
  ...
  'ext.EDataTables.*',
  ...

Using

Use similar to CGridView. If displayed in a normal call just run the widget. To fetch AJAX response send json encoded result of $widget->getFormattedData().

The action in a controller:

$widget=$this->createWidget('ext.EDataTables.EDataTables', array(
 'id'            => 'products',
 'dataProvider'  => $dataProvider,
 'ajaxUrl'       => Yii::app()->getBaseUrl().'/products/index',
 'columns'       => $columns,
));
if (!Yii::app()->getRequest()->getIsAjaxRequest()) {
  $this->render('index', array('widget' => $widget,));
  return;
} else {
  echo json_encode($widget->getFormattedData(intval($_REQUEST['sEcho'])));
  Yii::app()->end();
}

The index view (for non-ajax requests):

<?php $widget->run(); ?>

Preparing the dataprovider

To use features like sorting, pagination and filtering (by quick search field in the toolbar or a custom advanced search filter form) the dataprovider object passed to the widget must be prepared using provided EDTSort and EDTPagination class and CDbCriteria filled after parsing sent forms.

The simplest example:

$criteria = new CDbCriteria;
// bro-tip: $_REQUEST is like $_GET and $_POST combined
if (isset($_REQUEST['sSearch']) && isset($_REQUEST['sSearch']{0})) {
    // use operator ILIKE if using PostgreSQL to get case insensitive search
    $criteria->addSearchCondition('textColumn', $_REQUEST['sSearch'], true, 'AND', 'ILIKE');
}
 
$sort = new EDTSort('ModelClass', $sortableColumnNamesArray);
$sort->defaultOrder = 'id';
$pagination = new EDTPagination();
 
$dataProvider = new CActiveDataProvider('ModelClass', array(
    'criteria'      => $criteria,
    'pagination'    => $pagination,
    'sort'          => $sort,
))

An advanced example would be based on a search form defined with a model and a view. Its attributes would be then put into a critieria and passed to a dataProvider.

Other options

Check out the DataTables web page for docs regarding: * Table layout * Styling * Multi-column sorting etc. * Tons of examples and funky plugins

Todo

  • Documentation.
  • Support for more DataTables properties.
  • Checkbox column behaves different than in CGridView.

Coming soon

  • Docs on usage with external search filters.
  • Documentation how to process row selections (from checkbox column) and re-set them after page reload.
  • Docs how to use editable cells.

Resources

Total 8 comments

#6902 report it
nineinchnick at 2012/02/12 06:10am
pageSize and pagination

bilijen could You open a ticket on the projects page? We could discuss details there.

#6864 report it
bilijen at 2012/02/09 02:03pm
Same typo in Project wiki / pageSize and pagination

Please have a look at your Project wiki, too. Same typo there.

I've changed method getCurrentPage($recalculate=true) in EDTPagination.php like this:

public function getCurrentPage($recalculate=true)
    {
        if($this->_currentPage===null || $recalculate)
        {
            if(isset($_REQUEST[$this->startVar]) && isset($_REQUEST[$this->lengthVar]))
            {
                $this->_currentPage=floor(intval($_REQUEST[$this->startVar]) / $this->getPageSize());
                if($this->validateCurrentPage)
                {
                    $pageCount=ceil($this->getItemCount()/intval($_REQUEST[$this->lengthVar]));
                    if($this->_currentPage>=$pageCount)
                        $this->_currentPage=$pageCount-1;
                }
                if($this->_currentPage<0)
                    $this->_currentPage=0;
            }
            else
                $this->_currentPage=0;
        }
        return $this->_currentPage;
    }

in order to reflect a pageSize change.
$pageCount will now be computed correctly and pagination will work okay. (I've also exchanged pageVar for startVar in the entire class. Seems more logical to me).

Now the grid works pretty well. I can change pageSize, do paging, searching and sorting. The extension is a great piece of work. Thank you!

Regards.

#6861 report it
nineinchnick at 2012/02/09 12:21pm
Small but important addition to implementation description

That was a typo, fixing it now, thanks.

#6859 report it
bilijen at 2012/02/09 11:22am
Small but important addition to implementation description


In the above example of 'action in a controller' code I've changed the lines
$data = $widget->getFormattedData(intval($_REQUEST['sEcho']));
json_encode($data)
to
echo CJSON::encode($widget->getFormattedData(intval($_REQUEST['sEcho'])));
This is actually not my own idea but someone's suggestion on project's page.
You may as well use
$data = $widget->getFormattedData(intval($_REQUEST['sEcho']));
echo json_encode($data)

The 'echo' is important, otherwise the table will not redraw.

#6653 report it
nineinchnick at 2012/01/25 03:15pm
views

The example with createWidget is the action, I've added index and ajax views.

The idea is that you need the whole widget to extract table contents ready to be encoded into JSON and sent over in an AJAX response. That's why I create the widget in the action and pass it to the views. In a normal non-ajax view I just run the widget. The AJAX one just gets the data and encodes it.

Resetting all client scripts is kinda ugly, but it is needed as creating the widget registers some scripts.

Also, I've noticed some more leftover code in the getFormattedData method. If you get exceptions about non-existent properties try to remove those calls or wait for an update. I'm going to try to upload a new version ASAP.

BTW The DataTables plugin is awesome, this extension is merely a wrapper. I would advise buying the authors a beer through donations :-)

#6652 report it
rums at 2012/01/25 02:36pm
Not quite clear?

Hi,

Looks like a great extension. It works fine if I just use it as a drop-in for an existing CGridView -- changing $this->widget('zii.widgets.grid.CGridView'... to $this->widget('ext.EDataTables.EDataTables'... -- but I can't get the Ajax side of it working.

Can you clarify what piece and where you expect each chunk of code in the example to go? If this all goes in the controller (actionAdmin for example):

$widget=$this->createWidget('ext.EDataTables.EDataTables', array(
 'id'            => 'products',
 'dataProvider'  => $dataProvider,
 'ajaxUrl'       => Yii::app()->getBaseUrl().'/products/index',
 'columns'       => $columns,
));
if (!Yii::app()->getRequest()->getIsAjaxRequest()) {
  $this->render('index', array('widget' => $widget,));
  return;
}
$data = $widget->getFormattedData(intval($_REQUEST['sEcho']));
Yii::app()->getClientScript()->reset();
$this->renderPartial('ajax', array('dtData' => $data), false, true);

what goes in the view? I've tried a bunch of different ways of doing this and can't get it working. If you can post a the controller action and view code it would be greatly helpful. Thanks!

#6636 report it
nineinchnick at 2012/01/23 04:38pm
Property "CButtonColumn.sortable" is not defined.

Thanks for reporting. Should be fixed in the latest update.

#6630 report it
jmariani at 2012/01/23 11:16am
Property "CButtonColumn.sortable" is not defined.

Hi!

I got this error while trying your extension, on line

/Applications/MAMP/public_html/yiitest/protected/extensions/EDataTables/EDataTables.php(186)

Regards.

Leave a comment

Please to leave your comment.

Create extension