#Laravel 5 Datatable Builder
Based on chumper/datatable. It's an abstract class to implement the datatable like the form generator.
##Installation
Add on your composer.json
"require": {
"distilleries/datatable-builder": "1.*",
}
run composer update
.
Add Service provider to config/app.php
:
'providers' => [
// ...
'Distilleries\FormBuilder\FormBuilderServiceProvider',
'Distilleries\DatatableBuilder\DatatableBuilderServiceProvider',
]
And Facade (also in config/app.php
)
'aliases' => [
// ...
'FormBuilder' => 'Distilleries\FormBuilder\Facades\FormBuilder',
'Datatable' => 'Distilleries\DatatableBuilder\Facades\DatatableBuilder',
]
Add the javascript on your bower dependencies:
"dependencies": {
"datatables": "~1.10.4",
}
Export the configuration:
php artisan vendor:publish --provider="Distilleries\DatatableBuilder\DatatableBuilderServiceProvider"
Export the views (optional):
php artisan vendor:publish --provider="Distilleries\DatatableBuilder\DatatableBuilderServiceProvider" --tag="views"
Export the Javascript assets (optional):
Include the javascript with gulp or grunt vendor/distilleries/datatable-builder/resources/**/*
.
If you don't use a task manager or you want override the javascript just publish those with the command line:
php artisan vendor:publish --provider="Distilleries\DatatableBuilder\DatatableBuilderServiceProvider" --tag="assets"
You can find those in resources/assets/vendor/datatable-builder
.
Creating form classes is easy. With a simple artisan command I can create a datatable:
php artisan datatable:make Datatables/PostDatatable
you create form class in path app/Datatables/PostDatatable.php
that looks like this:
<?php namespace App\Datatables;
use Distilleries\DatatableBuilder\EloquentDatatable;
class PostDatatable extends EloquentDatatable
{
public function build()
{
// Add fields here...
$this->addDefaultAction();
}
}
You can add fields which you want when creating command like this:
php artisan datatable:make Datatables/SongDatatable --fields="name, lyrics"
And that will create a datatable in path app/Datatables/SongDatatable.php
with content:
<?php namespace App\Datatables;
use Distilleries\DatatableBuilder\EloquentDatatable;
class SongDatatable extends EloquentDatatable
{
public function build()
{
$this
->add('name',null,_('Name'))
->add('lyrics',null,_('Lyrics'));
$this->addDefaultAction();
}
}
The method add
have in param:
add($name, $closure = null, $translation = '', $orderable = true)
Param | Usage |
---|---|
name | Name of the column |
closure | Function with the model in parameter to return a template. By default null use the attribute of the model. |
translation | Translation of the column, by default empty use the column name |
orderable | Flag to handle column orderable state, by default true |
When you create a datatatable sometime the content need to be get from other table or stylize by a template like the actions buttons.
For example an address is link to a profile. To display the profile name on the datatable like the picture you can use the closure.
$this->add('profile_name', function ($model)
{
$profile = $model->profile;
return (empty($profile)?'':$profile->first_name . ' ' . $profile->last_name);
}, _('Profile'));
On my model Address
I have:
public function profile()
{
return $this->belongsTo('Profile');
}
You can return a template if you want:
$this->add('html_row', function ($model)
{
return View::make('admin.address.html_row',[
])->render();
});
You can override the base query for the datatable query.
By default it will send a fresh full Query: $this->model->newModelQuery();
/**
* {@inheritdoc}
*/
protected function baseQuery()
{
return $this->model->newModelQuery()
->selectRaw("id, data->>'$.title' AS title, data->>'$.chapo' AS intro, created_at");
}
You can use complex filter to filter your datatable. To do that I use the library FormBuilder. All the datatable have a plain form filter. If you had field on this form that display the filters.
For example we want all the user only online.
I create a choice field:
public function filters()
{
$this->form->add('status', 'choice', [
'choices' => StaticLabel::status(),
'empty_value' => _('-'),
'validation' => 'required',
'label' => _('Status')
]);
}
When the filters are submitted you can apply it with the method applyFilters
.
By default this method create a where with the name of the filter field if it's an attribute of the model.
If you want change this behaviour you can override it.
public function applyFilters()
{
$allInput = Input::all();
$columns = \Schema::getColumnListing($this->model->getTable());
foreach ($allInput as $name => $input)
{
if (in_array($name, $columns) and $input != '')
{
$this->model = $this->model->where($name, '=', $input);
}
}
}
If you don't want create a global scope of your model you just want restrict the display for this datatable.
you can use applyFilters
to do that.
For example I want display only the customer of the application: The datable work on the user model.
public function applyFilters()
{
parent::applyFilters();
$customer = \Role::where('initials', '==', '@c')->get()->last();
$this->model = $this->model->where('role_id', '=', $customer->id);
}
You want stylize your row to put it on green, blue or red.
You can do that with setClassRow
. By default this method check the status attribute.
If the status exist and it is empty we add the danger class to display it in red.
public function setClassRow($datatable)
{
$datatable->setRowClass(function ($row)
{
return (isset($row->status) and empty($row->status)) ? 'danger' : '';
});
return $datatable;
}
##Controller
You can use the trait Distilleries\DatatableBuilder\States\DatatableStateTrait
to add in your controller the default methods use with the datatable.
Example:
I created a controller app/Http/Controllers/DatatableController
:
<?php namespace App\Http\Controllers;
use App\Datatables\UserDatatable;
class DatatableController extends Controller {
use \Distilleries\DatatableBuilder\States\DatatableStateTrait;
/*
|--------------------------------------------------------------------------
| Welcome Controller
|--------------------------------------------------------------------------
|
| This controller renders the "marketing page" for the application and
| is configured to only allow guests. Like most of the other sample
| controllers, you are free to modify or remove it as you desire.
|
*/
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct(\App\User $model, UserDatatable $datatable)
{
$this->model = $model;
$this->datatable = $datatable;
}
/**
* Show the application welcome screen to the user.
*
* @return Response
*/
public function getIndex()
{
return view('welcome',[
'datatable'=>$this->getIndexDatatable()
]);
}
}
I add the controller on the route file :
Route::controllers([
'datatable' => 'DatatableController'
]);
Like you can see I inject the model and the datatable on the constructor. On the welcome template I put:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="//cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="//cdn.datatables.net/1.10.5/css/jquery.dataTables.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="/vendor/datatable-builder/js/datatable.js"></script>
</head>
<body>
<div class="container">
{!! $datatable !!}
</div>
</body>
</html>
That it you have your datatable from the user model.