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 feedback is needed. Please post issues on project's page.
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.
Extract into extensions dir.
Import in config/main.php
'import' => array( ... 'ext.EDataTables.*', ...
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):
$widget->run();
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.
Check out the DataTables web page for docs regarding:
Total 15 comments
Hi I agree that this is expensive, which is why I have a MyCGridView wrapper that avoids rendering when not needed (when configured to do so).
The extension should allow both the 'easy' way and the 'optimized way'. The 'easy way' is not that expensive in most cases, and speed of development is preferred. In some cases, optimization is needed. I have such a case and my views/widgets have several checks if rendering of the specific part is needed or not.
Anyway: I know how it is; one makes the extension for his own needs and shares with the community allowing the community to update, while in practice the community still expects the author to update...
Thanks for the feedback. It's always needed. Unfortunately, I don't want to do it the way you describe. EExcelView runs the whole action, then discards its output and generate its own. CGridView, when reloading data through AJAX, renders whole page and then extracts only the table with its contents. It's noted somewhere that this is not a preferred solution but it's there for simplicity. In my projects, rendering whole layout with menus etc. could be quite expensive because of auth checks and such. So there really is a need for a separate action to be called as a data source.
Another thing is performing a database search. There aren't any ready solutions in Yii, you have to create a criteria building mechanism yourself and pass it to dataprovider. I've written my own search() method in ActiveRecord that uses value from sEcho, validates it for every column and then puts it in a criteria object. Its quite complex, including checking auth items for relations etc.
There are lots of things to consider when building an index action and a simple widget doesn't have to cover them all.
Hi I tried this extension in order to port a CodeIgnite project to Yii and keep the same look and function for the moment. There is quite some work that has been done, but it is not a drop-in replacement for CGridView yet. I think that it should be possible to simply replace '...CGridView' with 'ext.EDataTables.EDataTables', but currently there is a need to have a different controller and add extra data. Look into EExcelView to look for some ideas. I think the controller code is currently needed because there is the need to reply with JSON. In EExcelView, there is a PDF or other reply. The applied solution is to clean the output buffers (ob_clean, hierarchically), and the output the JSON or whatever. The widget should check for sEcho, etc., and add the ajax code itself.
I had this error on Jquery using Yii 1.1.8: Uncaught TypeError: Object [object Object] has no method 'off' jdatatable.js:145
If I would want to use an array, I would put it into an CArrayDataProvider without any pagination but try to enable pagination by passing dataTables options in JavaScript. Full table would be available on page load and then dataTables would take over with pagination and sorting. There's no point in holding really large arrays in memory, so Ajax updates are not needed.
Another scenario is when you do read data through an Active or Sql DataProvider but have to postprocess it. Then you could just put it into an CArrayDataProvider.
Always remember to define the keyField.
Thnx for the Extension. Wanted to know if it is possible to just use it for Arrays instead of CDataProviders.
Thnx
I can load up the table fine from my dataProvider, and am using EDTSort and EDTPagination, but when I try to sort or view another page, all I get is an alert window showing an error and some data that starts like this:
Error 500: {"sEcho":2,"iTotalRecords":"17","iTotalDisplayRecords":"17","aaData":[["my data starts here...
Any ideas? Will there be an update or some new documentation soon? This extension has lots of potential but is very confusing to implement for a newbie like me.
bilijen could You open a ticket on the projects page? We could discuss details there.
Please have a look at your Project wiki, too. Same typo there.
I've changed method getCurrentPage($recalculate=true) in EDTPagination.php like this:
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.
That was a typo, fixing it now, thanks.
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.
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 :-)
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):
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!
Thanks for reporting. Should be fixed in the latest update.
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 login to leave your comment.