-
Notifications
You must be signed in to change notification settings - Fork 24
Quick Start
In this example you will learn how to use the DataTables plugin in the simplest fashion.
Use composer to install this plugin. Add the following repository and requirement to your composer.json:
"require": {
"ypnos-web/cakephp-datatables": "^3.0"
}
Load plugin in app/bootstrap.php:
Plugin::load('DataTables', ['bootstrap' => false, 'routes' => false]);
For example in your AppController:
class AppController extends Controller
{
public $helpers = [
'DataTables' => [
'className' => 'DataTables.DataTables'
]
];
public function initialize()
{
$this->loadComponent('DataTables.DataTables');
}
}
Include jQuery and jQuery DataTables scripts first and then the dataTables logic:
echo $this->Html->script([
'*PATH*/jquery.min.js',
'*PATH*/jquery.dataTables.min.js',
'*PATH*/dataTables.bootstrap.min.js', // optional
'DataTables.cakephp.dataTables.js',
]);
Include dataTables css:
echo $this->Html->css('*PATH*/dataTables.bootstrap.css');
If you don't use Bootstrap, see the DataTables documentation for which files to include instead. For FontAwesome, you might also want to have a look at this.
There is also a bunch of really helpful extensions for DataTables that we support, e.g. Scroller and Select.
There is two parts to DataTables from the Cake perspective:
- Adding a table with DataTables overlay in the view template
- Custom Controller logic to support DataTables AJAX requests
The DataTables helper provides a very easy method to create a table in your template:
public function table(string $id = 'datatable', array $dtOptions = [], array $htmlOptions = []) : string
This method generates a stub <table>
element and corresponding javascript which lets DataTables generate both heading and body of the table for us.
In this example of a table showing users, we also provide initial data to display:
$options = [
'ajax' => [
'url' => $this->Url->build() // current controller, action, params
],
'data' => $data,
'deferLoading' => $data->count(), // https://datatables.net/reference/option/deferLoading
'columns' => [
[
'data' => 'id',
'visible' => false,
'searchable' => false,
],
[
'title' => __('First Name'),
'data' => 'firstname'
],
[
'title' => __('Last Name'),
'data' => 'lastname'
],
[
'title' => __('Login name'),
'data' => 'username',
'className' => 'text-primary',
],
[
'title' => __('Department'),
'data' => 'department.name'
],
],
'order' => [3, 'asc'], // order by username
];
echo $this->DataTables->table('users-table', $options, ['class' => 'table table-striped']);
We could also not provide the initial data which would lead to dataTables using AJAX from the beginning. In this case, we would also omit the deferLoading
option.
Some notes on $dtOptions
(second argument):
- The array consists of options to DataTables as per the DataTables options reference.
- All columns need
data
defined so that DataTables can read the correct variable from$data
(which is provided in JSON format). The identifiers indata
therefore correspond to how the data is accessible from the view variable. - All columns need
title
defined if you do not provide a table heading in the HTML. - You can determine which columns should be searchable, orderable or even visible. An invisible column can be helpful for custom javascript callbacks which are discussed below.
- Some options are default in the plugin, e.g.
serverSide = true
, which you can overwrite if needed.
In the $htmlOptions
we provided Bootstrap CSS classes. The class dataTable
is always added.
As mentioned earlier, in the default configuration and above example, DataTables will serve the initially provided data first, but let the server process any new requests (e.g. pagination or scrolling using Scroller).
For this, in the controller, we replace our regular find operation with the wrapper provided by the plugin:
$data = $this->DataTables->find('Users', 'all', [
'contain' => ['Departments'],
'order' => ['username' => 'asc']
]);
$this->set('data', $data);
$this->set('_serialize', array_merge($this->viewVars['_serialize'], ['data']));
Again some notes on this example:
- The DataTables component provides a
find()
function that processes any parameters in the requests initiated by DataTables. It is a drop-in replacement for calling the table's finder directly. There is no need to differentiate between regular and JSON requests in the controller. - We provide a default order argument that needs to match the order argument in the template. Otherwise DataTables will indicate a wrong ordering to the user. This is related to our use of the
deferLoading
option. If you have any other custom settings for the initial data display, it is typically easier to not usedeferLoading
. - DataTables performs JSON requests and CakePHP's JSON view uses the
_serialize
view variable to determine which view variables to send back. The DataTables plugin sets a bunch of these, so it is crucial to append the data variable here. If your view variable is not called 'data', set DataTablesajax.dataSrc
option.
For columns that are defined as searchable or orderable, DataTables can offer search (i.e. filter) and ordering functionality to the user, respectively. To make this work on the server side, the DataTables component needs to know the column definitions, including the table fields that correspond to columns. We start by defining all columns in the controller (not the view, as before):
$columns = [
[
'field' => 'Users.id',
'data' => 'id',
'visible' => false,
'searchable' => false,
],
[
'title' => __('First Name'),
'field' => 'Users.firstname',
'data' => 'firstname'
],
[
'title' => __('Last Name'),
'field' => 'Users.lastname',
'data' => 'lastname'
],
[
'title' => __('Login name'),
'field' => 'Users.username',
'data' => 'username',
'className' => 'text-primary',
],
[
'title' => __('Department'),
'field' => 'Departments.name',
'data' => 'department.name'
],
];
$data = $this->DataTables->find('Users', 'all', [
'contain' => ['Departments'],
'order' => ['username' => 'asc']
], $columns);
$this->set('columns', $columns);
$this->set('data', $data);
$this->set('_serialize', array_merge($this->viewVars['_serialize'], ['data']));
Now, in the view, we use the view variable to pass on the same column definitions to the DataTables helper:
$options = [
'ajax' => [
'url' => $this->Url->build() // current controller, action, params
],
'data' => $data,
'deferLoading' => $data->count(), // https://datatables.net/reference/option/deferLoading
'columns' => $columns,
'order' => [3, 'asc'], // order by username
];
echo $this->DataTables->table('users-table', $options, ['class' => 'table table-striped']);
A drawback of this method is that styling options find their place in the controller, but would be better suited to stay in the view. You can alternatively extend the column definitions in the view. On the controller side, only the field names and, if applicable, searchable and orderable switches are needed (they are true by default).