Closed cbueche closed 11 years ago
By default, datatable processing is triggered if the request is an ajax one and the current action is index
. If this isn't the case, you can set the triggerAction
setting to the action you need as a string, or an array of multiple actions for that controller that should be triggered if the request is an ajax one. You can also set trigger
setting to a callback in your controller to do custom detection of when to process a request as a datatable request (it should return true/false).
Thanks for your willingness to help !
I see your point. I'm now using static code for the datatable part in my view to avoid side-effects, the code looks like this:
<script type="text/javascript">
$(document).ready(function() {
$('#dataTable').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": '<?php echo $this->Html->url(array("action" => "idt")); ?>'
} );
} );
</script>
Using FirebugLite, I then see a query going to the web server, the query looks like this:
GET /prolix/ck/devices/idt?sEcho=1&iColumns=13&sColumns=&iDisplayStart=0 .......
It has Content-Type "application/json", Accept "application/json, text/javascript, /; q=0.01", X-Requested-With "XMLHttpRequest" so I guess this a valid Ajax query trying to get action "idt" from controller "Device". So far so good.
The server answer is :
{
"code":"500",
"url":"\/prolix\/ck\/devices\/idt?sEcho=1&amp;iColumns=13&amp;sColumns=&amp;iDisplayStart=0 ...... ",
"name":"View file "\/Users\/cbueche\/Data\/Tools\/cakePHP\/prolix\/ck\/app\/View\/Devices\/json\/idt.ctp" is missing."
}
So it seems the handling of the request in Cake is wrong : it is trying to get a JSON view from View/Device/json/idt.ctp instead of View/Device/datatable/idt.ctp
Any idea why ?
Post your controller code. Include your action and how you configured the plugin (components array, etc). Btw you'll need a model get param like so:
echo $this->Html->url(array("action" => "idt", "?" => array("model" => "TheModelYouArePaginating"))
Here are all the parts you asked for :
DevicesController.php
<?php
App::uses('AppController', 'Controller');
/**
* Devices Controller
*
* @property Device $Device
*/
class DevicesController extends AppController {
# for JSON views and datatable
var $components = array(
'DataTable.DataTable' => array(
'columns' => array(
'id' => false, // bSearchable and bSortable will be false
'name' => 'Name', // bSearchable and bSortable will be true, with a custom label `Name`
// by default, the label with be a Inflector::humanize() version of the key
'mgmt_ip_4' => 'IP',
'Actions' => null, // tells DataTable that this column is not tied to a field
),
//'triggerAction' => array('idt'),
),
'RequestHandler',
);
public $helpers = array(
'Time',
'DataTable.DataTable' => array(
'scriptBlock' => false,
)
);
public $paginate = array(
'limit' => 2000,
'maxLimit' => 2000,
'order' => array(
'Customer.name' => 'asc',
'Device.name' => 'asc'
)
);
/**
* idt method
*
* @return void
*/
public function idt() {
$this->DataTable->paginate = array('Device');
$this->log("in idt", LOG_DEBUG);
}
... more methods ...
The action (currently not linked, calling it from the browser)
I'm not sure to understand where I will need the "model get param" you mention above. Is it simply a menu entry somewhere to call the below URL ?
http://127.0.0.1/prolix/ck/devices/idt
Model/Device.php
<?php
App::uses('AppModel', 'Model');
/**
* Device Model
*/
class Device extends AppModel {
public $belongsTo = array(
...
)
public $validate = array(
...
);
public function customSearch($field, $searchTerm, $columnSearchTerm, $conditions) {
if ($searchTerm) {
$conditions[] = array("$field LIKE" => '%' . $searchTerm); // only do left search
}
if ($columnSearchTerm) {
$conditions[] = array($field => $columnSearchTerm); // only do exact match
}
}
View/Devices/idt.ctp
<?php
$this->Html->script('DataTables/media/js/jquery.js', array('inline' => false));
$this->Html->script('DataTables/media/js/jquery.dataTables.js', array('inline' => false));
?>
<script type="text/javascript">
$(document).ready(function() {
$('#dataTable').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": '<?php echo $this->Html->url(array("action" => "idt")); ?>'
} );
} );
</script>
<div class="devices index">
<h2><?php echo __('Devices');?></h2>
<table id="dataTable" data-model="Device">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>IP</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="3">Loading data from server</td>
</tr>
</tbody>
</table>
</div>
...
View/Devices/datatable/idt.ctp
<?php
//debug($dtResults);
foreach($dtResults as $result) {
$this->dtResponse['aaData'][] = array(
$result['Device']['id'],
$result['Device']['name'],
$result['Device']['mgmt_ip_4'],
'actions',
);
}
route.php
...
Router::parseExtensions('json');
bootstrap.php
...
CakePlugin::load('DataTable');
Add:
var $components = array(
'DataTable.DataTable' => array(
'triggerAction' => array('idt')
Your sAjaxSource should be http://127.0.0.1/prolix/ck/devices/idt?model=Device
Bingo! It was lacking two things :
The desired functionality is present. However, I have one more problem to solve: the helper not rendering the javascript part (it looks like it does nothing). It works because I statically create the javascript code in the view :
<script type="text/javascript">
$(document).ready(function() {
$('#dataTable').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": '<?php echo $this->Html->url(array("action" => "idt", "?" => array("model" => "Device"))); ?>'
} );
} );
</script>
If I understand the doc correctly, instead of creating the javascript code above, I should be able to use this
$this->DataTable->render('Device');
in my View/Devices/idt.ctp, but it produces nothing. Any idea why ?
In the controller helpers var remove 'scriptBlock' => false
if you want to use the default init script. Also, add <?php echo $this->fetch('dataTableSettings'); ?>
before <?php echo $this->fetch('script'); ?>
$this->fetch('dataTableSettings');
outputs a js var with all the settings the jquery plugin needs - so if you don't want to use the default init script, you would use that js var for the settings (its needed for the default init script, also). Look at the page source to see its values and get an idea of what's going on behind the scenes.
Sorry for the lacking documentation.
Thanks Tigrang for all the help. The helper works and generate the javascript piece, but I then can't write my code so it works with datatables. Problem is mine, not yours, I'm stuck with lacking javascript know-how, and will need help from a local colleague, might take a few weeks to see him again.
meanwhile, I have reverted to coding the javascript entry in my view manually, it works this way, and the back-end works well. Thanks for your code, and let me know if you have a Paypal account so I can reward you for your work and code.
Regs, Charles
No problem. I hope you get it working soon. Works open-source and free, but if you feel like you want to donate anyways, it's tigrangab at gmail dot com
Hi,
I'm trying to use the plugin on top of a cakePHP 2.2.2 application. I have followed the README, but I have a problem with the Ajax calls, they are not going to the View/stuff/datatable/action.ctp. Instead, they are directed to View/stuff/action.ctp, which is my regular cake view file.
Then, datatable in the browser complains that the returning data is not JSON (of course it's not). In Firebug, I see an Ajax query going to stuff/action?long-params...
Maybe a reason, but not sure about its real impact : I upgraded the app from cakePHP 2.0, and I'm using JSON views elsewhere.
Help appreciated, TIA, Charles