diff --git a/add-column.md b/add-column.md index 5188d0a..d5b984c 100644 --- a/add-column.md +++ b/add-column.md @@ -1,19 +1,21 @@ # Add Column -You can add a custom column on your response by using `addColumn` api. +You can add a custom column to your response by using the `addColumn` api. + +> {note} added columns are assumed to be computed columns and not part of the database. Thus, search/sort will be disabled for those columns. If you need them, use the `editColumn` api instead. ## Add Column with Blade Syntax ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->addColumn('intro', 'Hi {{$name}}!') - ->make(true); + ->toJson(); }); ``` @@ -21,16 +23,16 @@ Route::get('user-data', function() { ## Add Column with Closure ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->addColumn('intro', function(User $user) { return 'Hi ' . $user->name . '!'; }) - ->make(true); + ->toJson(); }); ``` @@ -40,14 +42,14 @@ Route::get('user-data', function() { > {tip} You can use view to render your added column by passing the view path as the second argument on `addColumn` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->addColumn('intro', 'users.datatables.intro') - ->make(true); + ->toJson(); }); ``` @@ -62,13 +64,13 @@ Hi {{ $name }}! > {tip} Just pass the column order as the third argument of `addColumn` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->addColumn('intro', 'Hi {{$name}}!', 2) - ->make(true); + ->toJson(); }); ``` diff --git a/add-columns.md b/add-columns.md new file mode 100644 index 0000000..672ea15 --- /dev/null +++ b/add-columns.md @@ -0,0 +1,52 @@ +# Add Columns + +Add mutated / hidden columns. + + +## Add hidden model columns + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->addColumns(['foo','bar','buzz'=>"red"]) + ->toJson(); +}); +``` + + +## Example Response + +```json +{ + "draw": 2, + "recordsTotal": 10, + "recordsFiltered": 3, + "data": [{ + "id": 476, + "name": "Esmeralda Kulas", + "email": "abbott.cali@heaney.info", + "created_at": "2016-07-31 23:26:14", + "updated_at": "2016-07-31 23:26:14", + "deleted_at": null, + "superior_id": 0, + "foo":"value", + "bar":"value", + "buzz":"red" + }, { + "id": 6, + "name": "Zachery Muller", + "email": "abdullah.koelpin@yahoo.com", + "created_at": "2016-07-31 23:25:43", + "updated_at": "2016-07-31 23:25:43", + "deleted_at": null, + "superior_id": 1, + "foo":"value", + "bar":"value", + "buzz":"red" + }] +} +``` \ No newline at end of file diff --git a/blacklist.md b/blacklist.md index 2600340..a7950a4 100644 --- a/blacklist.md +++ b/blacklist.md @@ -3,13 +3,13 @@ Sorting and searching will not work on columns explicitly defined as blacklisted. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->blacklist(['password', 'name']) - ->make(true); + ->toJson(); }); -``` \ No newline at end of file +``` diff --git a/buttons-config.md b/buttons-config.md index 470c84c..817b62e 100644 --- a/buttons-config.md +++ b/buttons-config.md @@ -1,57 +1,62 @@ # Buttons Configurations + +## Artisan Console Configurations +Namespace configuration is used by the datatables command generator. + ```php -return [ - /** - * DataTables script view template. - */ - 'script_template' => 'datatables::script', - - /** - * Namespaces used by the generator. - */ - 'namespace' => [ - /** - * Base namespace/directory to create the new file. - * This is appended on default Laravel namespace. - * Usage: php artisan datatables:make User - * Output: App\DataTables\UserDataTable - * With Model: App\User (default model) - * Export filename: users_timestamp - */ - 'base' => 'DataTables', - - /** - * Base namespace/directory where your model's are located. - * This is appended on default Laravel namespace. - * Usage: php artisan datatables:make Post --model - * Output: App\DataTables\PostDataTable - * With Model: App\Post - * Export filename: posts_timestamp - */ - 'model' => '', - ], +'namespace' => [ + 'base' => 'DataTables', + 'model' => '', +], +``` + +### DataTable Base Namespace/Directory +This is the base namespace/directory to be created when a new DataTable is called. +This directory is appended to the default Laravel namespace. + +**Usage:** +```php artisan datatables:make User``` + +**Output:** +```App\DataTables\UserDataTable``` + +**Export filename:** ```users_(timestamp)``` + +### Model Option +This is the base namespace/directory where your models are located. +This directory is appended to the default Laravel namespace. +**Usage:** ```php artisan datatables:make Post --model``` +**Output:** ```App\DataTables\PostDataTable``` +**With Model:** ```App\Post`` +**Export filename:** ```posts_(timestamp)``` - /** - * PDF generator to be used when converting the table to pdf. - * Available generators: excel, snappy - * Snappy package: barryvdh/laravel-snappy - * Excel package: maatwebsite/excel - */ - 'pdf_generator' => 'excel', - - /** - * Snappy PDF options. - */ - 'snappy' => [ - 'options' => [ - 'no-outline' => true, - 'margin-left' => '0', - 'margin-right' => '0', - 'margin-top' => '10mm', - 'margin-bottom' => '10mm', - ], - 'orientation' => 'landscape', + +## PDF Generator +Set the PDF generator to be used when converting your dataTable to PDF. + +Available generators are: `excel`, `snappy` + +### Excel Generator +When `excel` is used as the generator, the package will use [`maatwebsite/excel`](http://www.maatwebsite.nl/laravel-excel/docs) to generate the PDF. + +> To export files to pdf, you will have to include "dompdf/dompdf": "~0.6.1", "mpdf/mpdf": "~5.7.3" or "tecnick.com/tcpdf": "~6.0.0" in your composer.json and change the export.pdf.driver config setting accordingly. + +### Snappy Generator (Default Generator) +When `snappy` is used as the generator, you need to install [`barryvdh/laravel-snappy`](https://github.com/barryvdh/laravel-snappy) + +### Snappy PDF Options +These are the options passed to `laravel-snappy` when exporting the pdf file. + +```php +'snappy' => [ + 'options' => [ + 'no-outline' => true, + 'margin-left' => '0', + 'margin-right' => '0', + 'margin-top' => '10mm', + 'margin-bottom' => '10mm', ], -]; + 'orientation' => 'landscape', +], ``` diff --git a/buttons-console.md b/buttons-console.md index 4c6b453..478ffcc 100644 --- a/buttons-console.md +++ b/buttons-console.md @@ -18,78 +18,89 @@ In this example, we will create a DataTable service class. php artisan datatables:make Posts ``` -This will create an `PostsDataTable` class on `app\DataTables` directory. +This will create a `PostsDataTable` class in the `app\DataTables` directory. ```php namespace App\DataTables; -use App\User; -use Yajra\Datatables\Services\DataTable; +use App\Models\Post; +use Illuminate\Database\Eloquent\Builder as QueryBuilder; +use Yajra\DataTables\EloquentDataTable; +use Yajra\DataTables\Html\Builder as HtmlBuilder; +use Yajra\DataTables\Html\Button; +use Yajra\DataTables\Html\Column; +use Yajra\DataTables\Html\Editor\Editor; +use Yajra\DataTables\Html\Editor\Fields; +use Yajra\DataTables\Services\DataTable; class PostsDataTable extends DataTable { /** - * Display ajax response. + * Build the DataTable class. * - * @return \Illuminate\Http\JsonResponse + * @param QueryBuilder $query Results from query() method. */ - public function ajax() + public function dataTable(QueryBuilder $query): EloquentDataTable { - return $this->datatables - ->eloquent($this->query()) - ->addColumn('action', 'path.to.action.view') - ->make(true); + return (new EloquentDataTable($query)) + ->addColumn('action', 'posts.action') + ->setRowId('id'); } /** - * Get the query object to be processed by dataTables. - * - * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Support\Collection + * Get the query source of dataTable. */ - public function query() + public function query(Post $model): QueryBuilder { - $query = User::query(); - - return $this->applyScopes($query); + return $model->newQuery(); } /** - * Optional method if you want to use html builder. - * - * @return \Yajra\Datatables\Html\Builder + * Optional method if you want to use the html builder. */ - public function html() + public function html(): HtmlBuilder { return $this->builder() + ->setTableId('posts-table') ->columns($this->getColumns()) - ->ajax('') - ->addAction(['width' => '80px']) - ->parameters($this->getBuilderParameters()); + ->minifiedAjax() + //->dom('Bfrtip') + ->orderBy(1) + ->selectStyleSingle() + ->buttons([ + Button::make('excel'), + Button::make('csv'), + Button::make('pdf'), + Button::make('print'), + Button::make('reset'), + Button::make('reload') + ]); } /** - * Get columns. - * - * @return array + * Get the dataTable columns definition. */ - protected function getColumns() + public function getColumns(): array { return [ - 'id', - // add your columns - 'created_at', - 'updated_at', + Column::computed('action') + ->exportable(false) + ->printable(false) + ->width(60) + ->addClass('text-center'), + Column::make('id'), + Column::make('add your columns'), + Column::make('created_at'), + Column::make('updated_at'), ]; } /** - * Get filename for export. - * - * @return string + * Get the filename for export. */ - protected function filename() + protected function filename(): string { - return 'posts_' . time(); + return 'Posts_' . date('YmdHis'); } } ``` @@ -99,12 +110,48 @@ class PostsDataTable extends DataTable In this example, we will pass a `--model` option to set the model to be used by our DataTable. ``` -php artisan datatables:make PostsDataTable --model=Post +php artisan datatables:make Posts --model +``` + +This will generate an `App\DataTables\PostsDataTable` class that uses `App\Post` as the base model for our query. +The exported filename will also be set to `posts_(timestamp)`. + + +### Model Namespace Option + +In this example, we will pass a `--model-namespace` option to set the model namespace to be used by our DataTable. + +``` +php artisan datatables:make Posts --model-namespace="Models\Client" ``` +It will implicitly activate `--model` option and override the `model` parameter in `datatables-buttons` config file. +This will allow to use a non-standard namespace if front-end and back-end models are in separate namespace for example. + + + +### Action Option + +In this example, we will use the `--action` option to set a custom path for the action column view. + +``` +php artisan datatables:make Posts --action="client.action" +``` +If no path is provided, a default path will be used. It will need to be changed thereafter. + +### Columns Option + +In this example, we will pass a `--columns` option to set the columns to be used by our DataTable. + +``` +php artisan datatables:make Posts --columns="id,title,author" +``` +If not provided, a default set of columns will be used. It will need to be manually changed thereafter. + + ## Creating a DataTable Scope service class -DataTable scope is class that we can use to limit our database search results based on the defined query scopes. +DataTable scope is a class that we can use to limit our database search results based on the defined query scopes. ``` php artisan datatables:scope ActiveUser @@ -115,7 +162,7 @@ This will create an `ActiveUser` class on `app\DataTables\Scopes` directory. ```php namespace App\DataTables\Scopes; -use Yajra\Datatables\Contracts\DataTableScopeContract; +use Yajra\DataTables\Contracts\DataTableScopeContract; class ActiveUser implements DataTableScopeContract { @@ -130,4 +177,4 @@ class ActiveUser implements DataTableScopeContract return $query->where('active', true); } } -``` \ No newline at end of file +``` diff --git a/buttons-custom.md b/buttons-custom.md new file mode 100644 index 0000000..714faec --- /dev/null +++ b/buttons-custom.md @@ -0,0 +1,40 @@ +# Custom Actions + +You can enable custom actions on your buttons as follows: + +Update `UsersDataTable` class and overload the `actions` property. Here we are +disabling the `csv` and `pdf` actions (so they cannot be fired by hijacking their +request) and enabling a `myCustomAction`. + + +```php +namespace App\DataTables; + +use App\User; +use Yajra\DataTables\Services\DataTable; + +class UsersDataTable extends DataTable +{ + protected array $actions = ['print', 'excel', 'myCustomAction']; + + public function html() + { + return $this->builder() + ->columns($this->getColumns()) + ->dom('Bfrtip') + ->buttons([ + 'print', + 'excel', + 'myCustomAction', + ]); + } + + public function myCustomAction() + { + //...your code here. + } + +} +``` + +Take a look at `Yajra\DataTables\Services\DataTable` to see how to fetch and manipulate the data (functions `excel`, `csv`, `pdf`). diff --git a/buttons-export.md b/buttons-export.md index b5d54e2..febf73e 100644 --- a/buttons-export.md +++ b/buttons-export.md @@ -10,7 +10,7 @@ Export button group includes `excel`, `csv` and `pdf` button. namespace App\DataTables; use App\User; -use Yajra\Datatables\Services\DataTable; +use Yajra\DataTables\Services\DataTable; class UsersDataTable extends DataTable { @@ -36,7 +36,7 @@ To enable exporting to excel, set `excel` on the buttons array. namespace App\DataTables; use App\User; -use Yajra\Datatables\Services\DataTable; +use Yajra\DataTables\Services\DataTable; class UsersDataTable extends DataTable { @@ -62,7 +62,7 @@ To enable exporting to csv, set `csv` on the buttons array. namespace App\DataTables; use App\User; -use Yajra\Datatables\Services\DataTable; +use Yajra\DataTables\Services\DataTable; class UsersDataTable extends DataTable { @@ -88,7 +88,7 @@ To enable exporting to pdf, set `pdf` on the buttons array. namespace App\DataTables; use App\User; -use Yajra\Datatables\Services\DataTable; +use Yajra\DataTables\Services\DataTable; class UsersDataTable extends DataTable { @@ -105,6 +105,40 @@ class UsersDataTable extends DataTable ... ``` + +## Export as Excel, CSV, and PDF using POST method + +To enable exporting to excel, csv, and pdf using POST method set the following on the buttons array. +This is recommended if you have a long query and if you are using IE browsers. + +```php +namespace App\DataTables; + +use App\User; +use Yajra\DataTables\Services\DataTable; + +class UsersDataTable extends DataTable +{ + //...some default stubs deleted for simplicity. + + public function html() + { + return $this->builder() + ->columns($this->getColumns()) + ->parameters([ + 'buttons' => ['postExcel', 'postCsv', 'postPdf'], + ]); + } +... +``` + +And also add this code to your routes.php file. +```php + Route::resource('sample', 'SampleController@index'); + Route::post('sample/export', 'SampleController@index'); +... +``` + ## Printable Version @@ -114,7 +148,7 @@ To enable print button, set `print` on the buttons array. namespace App\DataTables; use App\User; -use Yajra\Datatables\Services\DataTable; +use Yajra\DataTables\Services\DataTable; class UsersDataTable extends DataTable { @@ -129,4 +163,56 @@ class UsersDataTable extends DataTable ]); } ... -``` \ No newline at end of file +``` + + +## Reset Button + +To enable reset button, set `reset` on the buttons array. + +```php +namespace App\DataTables; + +use App\User; +use Yajra\DataTables\Services\DataTable; + +class UsersDataTable extends DataTable +{ + //...some default stubs deleted for simplicity. + + public function html() + { + return $this->builder() + ->columns($this->getColumns()) + ->parameters([ + 'buttons' => ['reset'], + ]); + } +... +``` + + +## Reload Button + +To enable reload button, set `reload` on the buttons array. + +```php +namespace App\DataTables; + +use App\User; +use Yajra\DataTables\Services\DataTable; + +class UsersDataTable extends DataTable +{ + //...some default stubs deleted for simplicity. + + public function html() + { + return $this->builder() + ->columns($this->getColumns()) + ->parameters([ + 'buttons' => ['reload'], + ]); + } +... +``` diff --git a/buttons-extended.md b/buttons-extended.md new file mode 100644 index 0000000..3753c44 --- /dev/null +++ b/buttons-extended.md @@ -0,0 +1,73 @@ +# Extended DataTable + +We can now extend and reuse our DataTable class inside our controller by using `before` and `response` callback. + +> IMPORTANT: Extended DataTable is only applicable on `^1.1` and above. + +## Upgrading from v1.0 to v1.1 + +- Upgrade to `laravel-datatables-buttons:^1.1` +- Rename `ajax()` method to `dataTable()` +- Remove `->toJson()` from the method chain. + +```php + public function ajax() + { + return $this->datatables + ->eloquent($this->query()) + ->addColumn('action', 'path.to.action.view') + ->toJson() + } +``` + +TO + + +```php + public function dataTable() + { + return $this->datatables + ->eloquent($this->query()) + ->addColumn('action', 'path.to.action.view'); + } +``` + +## Quick Example: + +```php +Route::get('datatable', function(RolesDataTable $dataTable){ + return $dataTable->before(function (\Yajra\DataTables\DataTableAbstract $dataTable) { + return $dataTable->addColumn('test', 'added inside controller'); + }) + ->response(function (\Illuminate\Support\Collection $response) { + $response['test'] = 'Append Data'; + + return $response; + }) + ->withHtml(function(\Yajra\DataTables\Html\Builder $builder) { + $builder->columns(['id', 'name', 'etc...']); + }) + ->with('key', 'value') + ->with([ + 'key2' => 'value2', + 'key3' => 'value3', + ]) + ->render('path.to.view'); +}); +``` + +## Passing data to DataTable class + +You can pass data from Controller to DataTable class using `with` api. + +```php +Route::get('datatable', function(RolesDataTable $dataTable){ + return $dataTable + ->with('key', 'value') + ->with([ + 'key2' => 'value2', + 'key3' => 'value3', + ]) + ->render('path.to.view'); +}); +``` diff --git a/buttons-fast-excel.md b/buttons-fast-excel.md new file mode 100644 index 0000000..fa04177 --- /dev/null +++ b/buttons-fast-excel.md @@ -0,0 +1,62 @@ +# Fast Excel Integration + +[Fast-Excel](https://github.com/rap2hpoutre/fast-excel) is recommended when exporting bulk records. + +## LIMITATIONS! + +FastExcel integration uses cursor behind the scene thus eager loaded columns will not work on export. You MUST use join statements if you want to export related columns. Also, column value formatting like converting boolean to Yes or No should be done on SQL LEVEL. + +## Usage + +1. Install `fast-excel` using `composer require rap2hpoutre/fast-excel`. +2. Create a dataTable class `php artisan datatables:make Users` +3. Adjust `UsersDataTable` as needed. +4. Set property `$fastExcel = true`. + +```php +class UsersDataTable extends DataTable +{ + protected $fastExcel = true; + + ... +} +``` + +5. DataTables will now export csv & excel using `fast-excel` package. + + +## Faster export by disabling the fast-excel callback + +1. Just set property `$fastExcelCallback = false`. This is enabled by default for a better formatted output of exported file. + +```php +class UsersDataTable extends DataTable +{ + protected $fastExcel = true; + protected $fastExcelCallback = false; + +``` + +2. Exported file will now be based on how your query was structured. No header formatting and all selected columns in sql will be included in the output. + +## Using custom callback + +Just override the `fastExcelCallback` method: + +```php +class UsersDataTable extends DataTable +{ + protected $fastExcel = true; + + public function fastExcelCallback() + { + return function ($row) { + return [ + 'Name' => $row['name'], + 'Email' => $row['email'], + ]; + }; + } + +... +``` \ No newline at end of file diff --git a/buttons-installation.md b/buttons-installation.md index c8d07f2..839f35b 100644 --- a/buttons-installation.md +++ b/buttons-installation.md @@ -1,21 +1,33 @@ -# Buttons Plugin Installation +# Buttons Plugin + +A Laravel DataTables plugin for handling server-side exporting of table as csv, excel, pdf, etc. + + +## Installation Run the following command in your project to get the latest version of the plugin: -`composer require yajra/laravel-datatables-buttons` +```shell +composer require yajra/laravel-datatables-buttons:^9.0 +``` + + +## Configuration + +> This step is optional if you are using Laravel 5.5+ Open the file ```config/app.php``` and then add following service provider. ```php 'providers' => [ // ... - Yajra\Datatables\DatatablesServiceProvider::class, - Yajra\Datatables\ButtonsServiceProvider::class, + Yajra\DataTables\DataTablesServiceProvider::class, + Yajra\DataTables\ButtonsServiceProvider::class, ], ``` After completing the step above, use the following command to publish configuration & assets: -``` +```shell php artisan vendor:publish --tag=datatables-buttons ``` diff --git a/buttons-laravel-excel.md b/buttons-laravel-excel.md new file mode 100644 index 0000000..3756cb3 --- /dev/null +++ b/buttons-laravel-excel.md @@ -0,0 +1,59 @@ +# Laravel Excel Integration + +[Laravel Excel](https://github.com/Maatwebsite/Laravel-Excel) is the default package used when exporting DataTables to Excel and CSV. + +## Using Export Class + +1. Create an export class `php artisan make:export UsersExport` +2. Update the generated export class and extend `DataTablesCollectionExport` + +```php +namespace App\Exports; + +use Yajra\DataTables\Exports\DataTablesCollectionExport; + +class UsersExport extends DataTablesCollectionExport +{ + +} +``` + +3. Update your `UsersDataTable` class and set `protected $exportClass = UsersExport::class` + +```php +class UsersDataTable extends DataTable +{ + protected $exportClass = UsersExport::class; + +``` + +4. Update your export class as needed. See official package docs: https://docs.laravel-excel.com/3.1/exports/collection.html + +## Example Export Class + +```php +namespace App\Exports; + +use Maatwebsite\Excel\Concerns\WithMapping; +use Yajra\DataTables\Exports\DataTablesCollectionExport; + +class UsersExport extends DataTablesCollectionExport implements WithMapping +{ + public function headings(): array + { + return [ + 'Name', + 'Email', + ]; + } + + public function map($row): array + { + return [ + $row['name'], + $row['email'], + ]; + } +} +``` + diff --git a/buttons-starter.md b/buttons-starter.md index 1229484..2b4a521 100644 --- a/buttons-starter.md +++ b/buttons-starter.md @@ -15,7 +15,7 @@ Update `UsersDataTable` class and set the columns and parameters needed to rende namespace App\DataTables; use App\User; -use Yajra\Datatables\Services\DataTable; +use Yajra\DataTables\Services\DataTable; class UsersDataTable extends DataTable { @@ -49,8 +49,7 @@ class UsersDataTable extends DataTable ```php use App\DataTables\UsersDataTable; -Route::get('users', function getUsers(UsersDataTable $dataTable) -{ +Route::get('users', function(UsersDataTable $dataTable) { return $dataTable->render('users.index'); }); ``` @@ -73,4 +72,4 @@ Our `users.index` view located at `resources/views/users/index.blade.php`. {!! $dataTable->scripts() !!} @endpush -``` \ No newline at end of file +``` diff --git a/buttons-with.md b/buttons-with.md new file mode 100644 index 0000000..b872b19 --- /dev/null +++ b/buttons-with.md @@ -0,0 +1,26 @@ +# Sending parameter to DataTable class +You can send a parameter from controller to dataTable class using `with` api. + + +## Example: + +```php +Route::get('datatable/{id}', function(UsersDataTable $dataTable, $id){ + return $dataTable->with('id', $id) + ->with([ + 'key2' => 'value2', + 'key3' => 'value3', + ]) + ->render('path.to.view'); +}); +``` + +You can then get the variable as a local property of the class. + +```php +class UsersDataTable { + public function query() { + return User::where('id', $this->id); + } +} +``` diff --git a/community-links.md b/community-links.md new file mode 100644 index 0000000..2f28828 --- /dev/null +++ b/community-links.md @@ -0,0 +1,15 @@ +# Community Links + +You may use the links below to further understand the Laravel Datatables. + + +## Articles +- [Laravel Datatables Tutorial With Example](https://appdividend.com/2018/04/16/laravel-datatables-tutorial-with-example/) +- [How to implement DataTables server-side in laravel](https://medium.com/justlaravel/how-to-implement-datatables-server-side-in-laravel-bcacf8472d70) +- [How to get started with DataTables in Laravel](https://dev.to/alphaolomi/how-to-get-started-with-datatables-in-laravel-9-5c39) + + +## Videos +- [Datatables in Laravel: Default and AJAX (Demo Project)](https://www.youtube.com/watch?v=1wgLY-V69MM) +- [DataTables - Server-side Processing in Laravel using Yajra](https://www.youtube.com/watch?v=zwz_cMvASCo) +- [Laravel 5.4 - how to use laravel datatables (yajra v.7.0)](https://www.youtube.com/watch?v=WKS6kO9zJQI) diff --git a/debugger.md b/debugger.md index 0c1e87c..25b6dd4 100644 --- a/debugger.md +++ b/debugger.md @@ -1,9 +1,11 @@ # Debugging Mode -To enable debugging mode, just set ```APP_DEBUG=true``` and the package will include the queries and inputs used when processing the table. +To enable debugging mode, just set `APP_DEBUG=true` and the package will include the queries and inputs used when processing the table. > IMPORTANT: Please make sure that APP_DEBUG is set to false when your app is on production. +You also need to update the [Error Handler](/docs/{{package}}/{{version}}/error-handler) config appropriately. + ## Example Response ```json { diff --git a/documentation.md b/documentation.md index e39643c..5397f22 100644 --- a/documentation.md +++ b/documentation.md @@ -1,76 +1,131 @@ -- Prologue - - [Release Notes](/docs/laravel-datatables/{{version}}/releases) - - [Upgrade Guide](/docs/laravel-datatables/{{version}}/upgrade) - - [Contribution Guide](/docs/laravel-datatables/{{version}}/contributing) - - [Security Issues](/docs/laravel-datatables/{{version}}/security) - - [API Documentation](http://yajra.github.io/laravel-datatables/api/{{version}}) -- Setup - - [Installation](/docs/laravel-datatables/{{version}}/installation) -- Getting Started - - [Introduction](/docs/laravel-datatables/{{version}}/introduction) - - [Demo Application](https://datatables.yajrabox.com/) -- Tutorials - - [Quick Starter](https://datatables.yajrabox.com/starter) - - [Service Implementation](https://datatables.yajrabox.com/service) -- Configuration - - [General Settings](/docs/laravel-datatables/{{version}}/general-settings) - - [Debugging Mode](/docs/laravel-datatables/{{version}}/debugger) -- Engines & Data Sources - - [Eloquent](/docs/laravel-datatables/{{version}}/engine-eloquent) - - [Query Builder](/docs/laravel-datatables/{{version}}/engine-query) - - [Collection](/docs/laravel-datatables/{{version}}/engine-collection) -- Response - - [Array Response](/docs/laravel-datatables/{{version}}/response-array) - - [Object Response](/docs/laravel-datatables/{{version}}/response-object) - - [Fractal Transformer](/docs/laravel-datatables/{{version}}/response-fractal) - - [Additional Data Response](/docs/laravel-datatables/{{version}}/response-with) -- Column Editing - - [Add Column](/docs/laravel-datatables/{{version}}/add-column) - - [Edit Column](/docs/laravel-datatables/{{version}}/edit-column) - - [Remove Column](/docs/laravel-datatables/{{version}}/remove-column) - - [Index Column](/docs/laravel-datatables/{{version}}/index-column) -- Row Editing - - [Row Options](/docs/laravel-datatables/{{version}}/row-options) - - [Row ID](/docs/laravel-datatables/{{version}}/row-options#row-id) - - [Row Class](/docs/laravel-datatables/{{version}}/row-options#row-class) - - [Row Data](/docs/laravel-datatables/{{version}}/row-options#row-data) - - [Row Attributes](/docs/laravel-datatables/{{version}}/row-options#row-attributes) -- Searching - - [Manual Search](/docs/laravel-datatables/{{version}}/manual-search) - - [Filter Column](/docs/laravel-datatables/{{version}}/filter-column) - - [Query Builder Extension](/docs/laravel-datatables/{{version}}/query-builder) - - [Regex Search](/docs/laravel-datatables/{{version}}/regex) -- Sorting/Ordering - - [Manual Order](/docs/laravel-datatables/{{version}}/manual-order) - - [Order Column](/docs/laravel-datatables/{{version}}/order-column) - - [Order Columns](/docs/laravel-datatables/{{version}}/order-columns) -- Utilities - - [XSS filtering](/docs/laravel-datatables/{{version}}/xss) - - [Blacklist Columns](/docs/laravel-datatables/{{version}}/blacklist) - - [Whitelist Columns](/docs/laravel-datatables/{{version}}/whitelist) - - [Set Total Records](/docs/laravel-datatables/{{version}}/set-total-records) - - [With Trashed](/docs/laravel-datatables/{{version}}/with-trashed) - - [Skip Paging](/docs/laravel-datatables/{{version}}/skip-paging) -- HTML Builder - - [Builder](/docs/laravel-datatables/{{version}}/html-builder) - - [Table](/docs/laravel-datatables/{{version}}/html-builder-table) - - [Columns](/docs/laravel-datatables/{{version}}/html-builder-column) - - [Ajax](/docs/laravel-datatables/{{version}}/html-builder-ajax) - - [Parameters](/docs/laravel-datatables/{{version}}/html-builder-parameters) - - [Events/Callbacks](/docs/laravel-datatables/{{version}}/html-builder-callbacks) - - [Add Action](/docs/laravel-datatables/{{version}}/html-builder-action) - - [Add Checkbox](/docs/laravel-datatables/{{version}}/html-builder-checkbox) - - [Add Index](/docs/laravel-datatables/{{version}}/html-builder-index) +- ## Prologue + - [Release Notes](/docs/{{package}}/{{version}}/releases) + - [Upgrade Guide](/docs/{{package}}/{{version}}/upgrade) + - [Contribution Guide](/docs/{{package}}/{{version}}/contributing) + - [Security Issues](/docs/{{package}}/{{version}}/security) + +- ## Getting Started + - [Introduction](/docs/{{package}}/{{version}}/introduction) + - [Installation](/docs/{{package}}/{{version}}/installation) + - [Community Links](/docs/{{package}}/{{version}}/community-links) + +- ## Tutorials + - [Quick Starter](/docs/{{package}}/{{version}}/quick-starter) + +- ## Configuration + - [General Settings](/docs/{{package}}/{{version}}/general-settings) + - [Debugging Mode](/docs/{{package}}/{{version}}/debugger) + - [Error Handler](/docs/{{package}}/{{version}}/error-handler) + +- ## DataTables Classes + - [Eloquent](/docs/{{package}}/{{version}}/engine-eloquent) + - [Query Builder](/docs/{{package}}/{{version}}/engine-query) + - [Collection](/docs/{{package}}/{{version}}/engine-collection) + +- ## Response + - [Array Response](/docs/{{package}}/{{version}}/response-array) + - [Object Response](/docs/{{package}}/{{version}}/response-object) + - [Additional Data Response](/docs/{{package}}/{{version}}/response-with) + - [Only Columns](/docs/{{package}}/{{version}}/response-only) + - [Response Resource](/docs/{{package}}/{{version}}/response-resource) + +- ## Column Editing + - [Add Column](/docs/{{package}}/{{version}}/add-column) + - [Add Columns](/docs/{{package}}/{{version}}/add-columns) + - [Edit Column](/docs/{{package}}/{{version}}/edit-column) + - [Remove Column](/docs/{{package}}/{{version}}/remove-column) + - [Index Column](/docs/{{package}}/{{version}}/index-column) + - [Raw Columns](/docs/{{package}}/{{version}}/raw-columns) + - [Export Columns](/docs/{{package}}/{{version}}/export-column) + - [Print Columns](/docs/{{package}}/{{version}}/print-column) + +- ## Row Editing + - [Row Options](/docs/{{package}}/{{version}}/row-options) + - [Row ID](/docs/{{package}}/{{version}}/row-options#row-id) + - [Row Class](/docs/{{package}}/{{version}}/row-options#row-class) + - [Row Data](/docs/{{package}}/{{version}}/row-options#row-data) + - [Row Attributes](/docs/{{package}}/{{version}}/row-options#row-attributes) + +- ## Searching + - [Manual Search](/docs/{{package}}/{{version}}/manual-search) + - [Filter Column](/docs/{{package}}/{{version}}/filter-column) + - [Regex Search](/docs/{{package}}/{{version}}/regex) + - [Smart Search](/docs/{{package}}/{{version}}/smart-search) + - [Starts With Search](/docs/{{package}}/{{version}}/starts-with-search) + - [Relationships](/docs/{{package}}/{{version}}/relationships) + - [Scout Search](/docs/{{package}}/{{version}}/scout-search) + +- ## Sorting/Ordering + - [Manual Order](/docs/{{package}}/{{version}}/manual-order) + - [Order Column](/docs/{{package}}/{{version}}/order-column) + - [Order Columns](/docs/{{package}}/{{version}}/order-columns) + - [Order By Nulls Last](/docs/{{package}}/{{version}}/order-by-nulls-last) + +- ## SearchPanes + - [SearchPanes Extension](/docs/{{package}}/{{version}}/search-panes-starter) + - [Hide Columns in SearchPanes](/docs/{{package}}/{{version}}/search-panes-hide-columns) + - [Further options](/docs/{{package}}/{{version}}/search-panes-options) + +- ## Utilities + - [XSS filtering](/docs/{{package}}/{{version}}/xss) + - [Blacklist Columns](/docs/{{package}}/{{version}}/blacklist) + - [Whitelist Columns](/docs/{{package}}/{{version}}/whitelist) + - [Set Total Records](/docs/{{package}}/{{version}}/set-total-records) + - [Skip Total Records](/docs/{{package}}/{{version}}/skip-total-records) + - [Set Filtered Records](/docs/{{package}}/{{version}}/set-filtered-records) + - [Skip Paging](/docs/{{package}}/{{version}}/skip-paging) ### PLUGINS -- Buttons - - [Installation](/docs/laravel-datatables/{{version}}/buttons-installation) - - [Configuration](/docs/laravel-datatables/{{version}}/buttons-config) - - [Quick Starter](/docs/laravel-datatables/{{version}}/buttons-starter) - - [Excel](/docs/laravel-datatables/{{version}}/buttons-export#excel) - - [CSV](/docs/laravel-datatables/{{version}}/buttons-export#csv) - - [PDF](/docs/laravel-datatables/{{version}}/buttons-export#pdf) - - [Print](/docs/laravel-datatables/{{version}}/buttons-export#print) - - [Artisan Console](/docs/laravel-datatables/{{version}}/buttons-console) +- ## Html + - [Installation](/docs/{{package}}/{{version}}/html-installation) + - [Builder](/docs/{{package}}/{{version}}/html-builder) + - [Table](/docs/{{package}}/{{version}}/html-builder-table) + - [Config](/docs/{{package}}/{{version}}/html-builder-config) + - [Columns](/docs/{{package}}/{{version}}/html-builder-column) + - [Column Builder](/docs/{{package}}/{{version}}/html-builder-column-builder) + - [Macro](/docs/{{package}}/{{version}}/html-builder-macro) + - [Ajax](/docs/{{package}}/{{version}}/html-builder-ajax) + - [Minified Ajax](/docs/{{package}}/{{version}}/html-builder-minified-ajax) + - [Post Ajax](/docs/{{package}}/{{version}}/html-builder-post-ajax) + - [Parameters](/docs/{{package}}/{{version}}/html-builder-parameters) + - [Events/Callbacks](/docs/{{package}}/{{version}}/html-builder-callbacks) + - [Add Action](/docs/{{package}}/{{version}}/html-builder-action) + - [Add Checkbox](/docs/{{package}}/{{version}}/html-builder-checkbox) + - [Add Index](/docs/{{package}}/{{version}}/html-builder-index) + - [Additional Scripts](/docs/{{package}}/{{version}}/html-builder-additional-scripts) + - [Github](https://github.com/yajra/laravel-datatables-html) + +- ## Buttons + - [Installation](/docs/{{package}}/{{version}}/buttons-installation) + - [Configuration](/docs/{{package}}/{{version}}/buttons-config) + - [Quick Starter](/docs/{{package}}/{{version}}/buttons-starter) + - [DataTable Buttons](/docs/{{package}}/{{version}}/buttons-export) + - [Custom Actions](/docs/{{package}}/{{version}}/buttons-custom) + - [Sending Parameters](/docs/{{package}}/{{version}}/buttons-with) + - [Extended DataTable](/docs/{{package}}/{{version}}/buttons-extended) + - [Buttons Command](/docs/{{package}}/{{version}}/buttons-console) + - [Laravel Excel Export](/docs/{{package}}/{{version}}/buttons-laravel-excel) + - [Fast Excel Export](/docs/{{package}}/{{version}}/buttons-fast-excel) + - [Github](https://github.com/yajra/laravel-datatables-buttons) + +- ## Fractal + - [Installation](/docs/{{package}}/{{version}}/fractal-installation) + - [Fractal Transformer](/docs/{{package}}/{{version}}/response-fractal) + - [Fractal Serializer](/docs/{{package}}/{{version}}/response-fractal-serializer) + +- ## Export + - [Installation](/docs/{{package}}/{{version}}/exports-installation) + - [Usage](/docs/{{package}}/{{version}}/exports-usage) + - [Purge](/docs/{{package}}/{{version}}/exports-purge) + - [Options](/docs/{{package}}/{{version}}/exports-options) +- ## Editor + - [Installation](/docs/{{package}}/{{version}}/editor-installation) + - [Editor Command](/docs/{{package}}/{{version}}/editor-command) + - [Editor Model](/docs/{{package}}/{{version}}/editor-model) + - [Editor Rules](/docs/{{package}}/{{version}}/editor-rules) + - [Event Hooks](/docs/{{package}}/{{version}}/editor-events) + - [Usage](/docs/{{package}}/{{version}}/editor-usage) + - [Tutorial](/docs/{{package}}/{{version}}/editor-tutorial) + - [Github](https://github.com/yajra/laravel-datatables-editor) diff --git a/edit-column.md b/edit-column.md index 86463c6..022cfb7 100644 --- a/edit-column.md +++ b/edit-column.md @@ -6,14 +6,14 @@ You can edit a column on your response by using `editColumn` api. ## Edit Column with Blade Syntax ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->editColumn('name', 'Hi {{$name}}!') - ->make(true); + ->toJson(); }); ``` @@ -21,16 +21,16 @@ Route::get('user-data', function() { ## Edit Column with Closure ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->editColumn('name', function(User $user) { return 'Hi ' . $user->name . '!'; }) - ->make(true); + ->toJson(); }); ``` @@ -40,18 +40,75 @@ Route::get('user-data', function() { > {tip} You can use view to render your added column by passing the view path as the second argument on `editColumn` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) - ->editColumn('name', 'users.datatables.into') - ->make(true); + return DataTables::eloquent($model) + ->editColumn('name', 'users.datatables.name') + ->toJson(); + }); ``` Then create your view on `resources/views/users/datatables/name.blade.php`. + ```php Hi {{ $name }}! ``` + + +## Edit Column with View and Data + +> {tip} You can use view to render your added column by passing the view path as the second argument on `editColumn` api. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + $externalData = 'External'; + + return DataTables::eloquent($model) + ->editColumn('name', ['users.datatables.name', [ + 'externalData' => $externalData, + ]]) + ->toJson(); + +}); +``` + +Then create your view on `resources/views/users/datatables/name.blade.php`. + +```php +Hi {{ $name }}! + +Here is some external data: {{ $externalData }}. +``` + + + +## Edit only the requested Columns + +> {tip} You can skip editing the columns that are not in your requested payload by using `editOnlySelectedColumns` before using `editColumn` + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->editColumn('id', function () { + return view('users.datatables.id'); // View will always be rendered + }) + ->editOnlySelectedColumns() + ->editColumn('name', function () { + return 'Hi ' . $user->name . '!'; // View will only be rendered if the column is in the payload + only if in the payload + }) + ->toJson(); +}); +``` diff --git a/editor-command.md b/editor-command.md new file mode 100644 index 0000000..cb6ff9c --- /dev/null +++ b/editor-command.md @@ -0,0 +1,163 @@ +# DataTables Editor Command + +## Introduction + +Artisan is the command-line interface included with Laravel. +It provides a number of helpful commands that can assist you while you build your application. +To view a list of all available Artisan commands, you may use the list command: + +```bash +php artisan list +``` + + +## Editor Command + +```bash +php artisan datatables:editor {name} +``` + + +## Editor Command Options + +- `--model` : The name given will be used as the model is singular form. +- `--model-namespace` : The namespace of the model to be used. + + +## Creating a DataTables Editor class + +In this example, we will create a DataTable Editor class. + +```bash +php artisan datatables:editor Posts +``` + +This will create a `PostsDataTableEditor` class on `app\DataTables` directory. + +```php +namespace App\DataTables; + +use Illuminate\Database\Eloquent\Model; +use Illuminate\Validation\Rule; +use Yajra\DataTables\DataTablesEditor; +use App\User; + +class PostsDataTableEditor extends DataTablesEditor +{ + protected $model = User::class; + + /** + * Get create action validation rules. + * + * @return array + */ + public function createRules() + { + return [ + 'email' => 'required|email', + 'name' => 'required', + ]; + } + + /** + * Get edit action validation rules. + * + * @param Model $model + * @return array + */ + public function editRules(Model $model) + { + return [ + 'email' => 'sometimes|required|email|' . Rule::unique($model->getTable())->ignore($model->getKey()), + 'name' => 'sometimes|required', + ]; + } + + /** + * Get remove action validation rules. + * + * @param Model $model + * @return array + */ + public function removeRules(Model $model) + { + return []; + } +} +``` + + +### Model Option + +In this example, we will pass a `--model` option to set the model to be used by our DataTable. + +```bash +php artisan datatables:editor Posts --model +``` + +This will generate a `App\DataTables\PostsDataTable` class that uses `App\Post` as the base model for our query. +The exported filename will also be set to `posts_(timestamp)`. + +```php +namespace App\DataTables; + +use Illuminate\Database\Eloquent\Model; +use Illuminate\Validation\Rule; +use Yajra\DataTables\DataTablesEditor; +use App\Post; + +class PostsDataTableEditor extends DataTablesEditor +{ + protected $model = Post::class; + + /** + * Get create action validation rules. + * + * @return array + */ + public function createRules() + { + return [ + 'email' => 'required|email', + 'name' => 'required', + ]; + } + + /** + * Get edit action validation rules. + * + * @param Model $model + * @return array + */ + public function editRules(Model $model) + { + return [ + 'email' => 'sometimes|required|email|' . Rule::unique($model->getTable())->ignore($model->getKey()), + 'name' => 'sometimes|required', + ]; + } + + /** + * Get remove action validation rules. + * + * @param Model $model + * @return array + */ + public function removeRules(Model $model) + { + return []; + } +} +``` + + +### Model Namespace Option + +In this example, we will pass a `--model-namespace` option to set the model namespace to be used by our DataTable. + +```bash +php artisan datatables:editor Posts --model-namespace="Entities" +``` + +It will implicitly activate `--model` option and override the `model` parameter in `datatables-buttons` config file. +This will allow to use a non-standard namespace if front-end and back-end models are in separate namespace for example. diff --git a/editor-events.md b/editor-events.md new file mode 100644 index 0000000..9eb2b4a --- /dev/null +++ b/editor-events.md @@ -0,0 +1,215 @@ +# DataTables Editor Event Hooks + +In addition to Laravel's model events, DataTables Editor offers some pre & post event hooks. + + +## Create Events + +Create action has the following event hooks: + +- `creating` event hook that is fired before creating a new record. +- `created` event hook that is fired after the record was created. + +To use the event hook, just add the methods on your editor class. + +```php +/** + * Event hook that is fired before creating a new record. + * + * @param \Illuminate\Database\Eloquent\Model $model Empty model instance. + * @param array $data Attribute values array received from Editor. + * @return array The updated attribute values array. + */ +public function creating(Model $model, array $data) +{ + // Code can change the attribute values array before saving data to the + // database. + // Can be used to initialize values on new model. + + // Since arrays are copied when passed by value, the function must return + // the updated $data array + return $data; +} + +/** + * Event hook that is fired after a new record is created. + * + * @param \Illuminate\Database\Eloquent\Model $model The newly created model. + * @param array $data Attribute values array received from `creating` or + * `saving` hook. + * @return \Illuminate\Database\Eloquent\Model Since version 1.8.0 it must + * return the $model. + */ +public function created(Model $model, array $data) +{ + // Can be used to mutate state of newly created model that is returned to + // Editor. + + // Prior to version 1.8.0 of Laravel DataTables Editor the hook was not + // required to return the $model. + // In version 1.8.0+ the hook must return the $model instance: + return $model; +} +``` + + +## Edit Events + +Edit action has the following event hooks: + +- `updating` event hook that is fired before updating an existing record. +- `updated` event hook that is fired after the record was updated. + +To use the event hook, just add the methods on your editor class. + +```php +/** + * Event hook that is fired before updating an existing record. + * + * @param \Illuminate\Database\Eloquent\Model $model Model instance retrived + * retrived from database. + * @param array $data Attribute values array received from Editor. + * @return array The updated attribute values array. + */ +public function updating(Model $model, array $data) { + // Can be used to modify the attribute values received from Editor before + // applying changes to model. + + // Since arrays are copied when passed by value, the function must return + // the updated $data array + return $data; +} + +/** + * Event hook that is fired after the record was updated. + * + * @param \Illuminate\Database\Eloquent\Model $model Updated model instance. + * @param array $data Attribute values array received from `updating` or + * `saving` hook. + * @return \Illuminate\Database\Eloquent\Model Since version 1.8.0 it must + * return the $model. + */ +public function updated(Model $model, array $data) { + // Can be used to mutate state of updated model that is returned to Editor. + + // Prior to version 1.8.0 of Laravel DataTables Editor the hook was not required + // to return the $model. + // In version 1.8.0+ the hook must return the $model instance: + return $model; +} +``` + + +## Save events + +In addition to create and edit events, the following save event hooks are available: + +- `saving` event hook that is fired after `creating` and `updating` events, but + before the model is saved to the database. +- `saved` event hook that is fired after `created` and `updated` events. + +To use the event hook, just add the method on your editor class: + +```php +/** + * Event hook that is fired after `creating` and `updating` hooks, but before + * the model is saved to the database. + * + * @param \Illuminate\Database\Eloquent\Model $model Empty model when creating; + * Original model when updating. + * @param array $data Attribute values array received from `creating` or + * `updating` event hook. + * @return array The updated attribute values array. + */ +public function saving(Model $model, array $data) +{ + // The event hook can be used to modify the $data array that is used to + // create or update the record. + + // Since arrays are copied when passed by value, the function must return + // the updated $data array + return $data; +} + +/** + * Event hook that is fired after `created` and `updated` events. + * + * @param \Illuminate\Database\Eloquent\Model $model The new model when + * creating; the updated model when updating. + * @param array $data Attribute values array received from `creating`, + * `updating`, or `saving`. + * @return \Illuminate\Database\Eloquent\Model Since version 1.8.0 it must + * return the $model. + */ +public function saved(Model $model, array $data) +{ + // Can be used to mutate state of updated model that is returned to Editor. + + // Prior to version 1.8.0 of Laravel DataTables Editor the hook was not required + // to return the $model. + // In version 1.8.0+ the hook must return the $model instance: + return $model; +} +``` + + +## Remove Events + +Remove action has the following event hooks: + +- `deleting` event hook that is fired before deleting a record. +- `deleted` event hook that is fired after the record was deleted. + +To use the event hook, just add the methods on your editor class. + +```php +/** + * Event hook that is fired before deleting an existing record. + * + * @param \Illuminate\Database\Eloquent\Model $model The original model + * retrieved from database. + * @param array $data Attribute values array received from Editor. + * @return void + */ +public function deleting(Model $model, array $data) { + // Record still exists in database. Code can be used to delete records from + // child tables that don't specify cascade deletes on the foreign key + // definition. +} + +/** + * Event hook that is fired after deleting the record from database. + * + * @param \Illuminate\Database\Eloquent\Model $model The original model + * retrieved from database. + * @param array $data Attribute values array received from Editor. + * @return void + */ +public function deleted(Model $model, array $data) { + // Record no longer exists in database, but $model instance still contains + // data as it was before deleting. Any changes to the $model instance will + // be returned to Editor. +} +``` + + +## Upload Events + +Upload action has the following event hooks: + +- `uploaded` event hook that is fired after a file was uploaded. + +To use the event hook, just add the methods on your editor class. + +```php +/** + * Event hook that is fired after uploading a file. + * + * @param string $id The auto-generated file id from filesystem. + * @return string + */ +public function uploaded($id) { + // return the file id. + return $id; +} +``` diff --git a/editor-installation.md b/editor-installation.md new file mode 100644 index 0000000..c4c95b6 --- /dev/null +++ b/editor-installation.md @@ -0,0 +1,30 @@ +# DataTables Editor Plugin + +This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for processing [DataTables Editor](https://editor.datatables.net/) library. + +> {tip} Special thanks to [@bellwood](https://github.com/bellwood) and [@DataTables](https://github.com/datatables) for being [generous](https://github.com/yajra/laravel-datatables/issues/1548) for providing a license to support the development of this package. + +A [premium license](https://editor.datatables.net/purchase/index) is required to be able to use [DataTables Editor](https://editor.datatables.net/) library. + + +## Installation + +Run the following command in your project to get the latest version of the plugin: + +`composer require yajra/laravel-datatables-editor:^1.0` + + +## Configuration + +> This step is optional if you are using Laravel 5.5 + +Open the file ```config/app.php``` and then add following service provider. + +```php +'providers' => [ + // ... + Yajra\DataTables\EditorServiceProvider::class, +], +``` + +And that's it! Start building out some awesome DataTables Editor! diff --git a/editor-model.md b/editor-model.md new file mode 100644 index 0000000..31166f6 --- /dev/null +++ b/editor-model.md @@ -0,0 +1,37 @@ +# DataTables Editor Model + +DataTables Editor requires a `Eloquent Model` that will be used for our CRUD operations. + +> {tip} All CRUD operations of Editor uses database transaction. + + +## Setup Model + +Just set the `$model` property of your editor class to your model's FQCN. + +```php +namespace App\DataTables\Editors; + +use App\User; +use Yajra\DataTables\DataTablesEditor; + +class UsersDataTablesEditor extends DataTablesEditor +{ + protected $model = User::class; +} +``` + +## Fillable Property + +Don't forget to set your model's fillable property. The Editor's basic crud operation relies on this. +For advance operations like saving relations, use the [Editors Event Hooks](/docs/{{package}}/{{version}}/editor-events). + +```php +class User extends Model { + protected $fillable = [ + 'name', + 'email', + 'password', + ]; +} +``` \ No newline at end of file diff --git a/editor-rules.md b/editor-rules.md new file mode 100644 index 0000000..b5437e8 --- /dev/null +++ b/editor-rules.md @@ -0,0 +1,56 @@ +# DataTables Editor Rules + +DataTables Editor requires three (3) rules for create, edit and remove action respectively. + + +## Create Rules + +This are the rules that will be used when validating a create action. + +```php +public function createRules() { + return [ + 'email' => 'required|email|unique:users', + 'name' => 'required', + ]; +} +``` + + +## Edit Rules + +This are the rules that will be used when validating an edit action. + +```php +public function editRules(Model $model) { + return [ + 'email' => 'sometimes|required|email|' . Rule::unique($model->getTable())->ignore($model->getKey()), + 'first_name' => 'sometimes|required', + ]; +} +``` + + +## Remove Rules + +This are the rules that will be used when validating a remove action. + +```php +public function removeRules(Model $model) { + return []; +} +``` + + +## Upload Rules + +This are the rules that will be used when validating an upload action. + +```php +public function uploadRules() { + return [ + 'avatar' => 'required|image', + 'resume' => 'required|mimes:pdf', + ]; +} +``` diff --git a/editor-tutorial.md b/editor-tutorial.md new file mode 100644 index 0000000..caff59b --- /dev/null +++ b/editor-tutorial.md @@ -0,0 +1,207 @@ +# Laravel 10 CRUD with DataTables Editor. + +Before we begin, please be reminded that the Editor library that we are going to use here requires a paid license. +See [DataTables Editor](https://editor.datatables.net/purchase/index) for details. + +## Pre-requisites + +This tutorial requires https://yajrabox.com/docs/laravel-datatables/10.0/quick-starter. + +## Editor License + +Copy and rename your `Editor.XX.zip` to `Editor.zip` and move it to project folder. + +## Register postinstall script to package.json + +```json + "scripts": { + "dev": "vite", + "build": "vite build", + "postinstall": "node node_modules/datatables.net-editor/install.js ./Editor.zip" + }, +``` + +## Install DataTables Editor assets. + +```sh +npm i datatables.net-editor datatables.net-editor-bs5 +``` + +## Register editor script on `resources/js/app.js` + +```js +import './bootstrap'; +import 'laravel-datatables-vite'; + +import "datatables.net-editor"; +import Editor from "datatables.net-editor-bs5"; +Editor(window, $); +``` + +## Add editor styles on `resources/sass/app.scss`. + +```css +// Fonts +@import url('https://fonts.bunny.net/css?family=Nunito'); + +// Variables +@import 'variables'; + +// Bootstrap +@import 'bootstrap/scss/bootstrap'; + +// DataTables +@import 'bootstrap-icons/font/bootstrap-icons.css'; +@import "datatables.net-bs5/css/dataTables.bootstrap5.css"; +@import "datatables.net-buttons-bs5/css/buttons.bootstrap5.css"; +@import "datatables.net-editor-bs5/css/editor.bootstrap5.css"; +@import 'datatables.net-select-bs5/css/select.bootstrap5.css'; +``` + +## Recompile assets. + +```sh +npm run dev +``` + +### UsersDataTable.php + +Create a new editor instance and add some fields for name and email. + +```php +namespace App\DataTables; + +use App\Models\User; +use Illuminate\Database\Eloquent\Builder as QueryBuilder; +use Yajra\DataTables\EloquentDataTable; +use Yajra\DataTables\Html\Builder as HtmlBuilder; +use Yajra\DataTables\Html\Button; +use Yajra\DataTables\Html\Column; +use Yajra\DataTables\Html\Editor\Editor; +use Yajra\DataTables\Html\Editor\Fields; +use Yajra\DataTables\Services\DataTable; + +class UsersDataTable extends DataTable +{ + /** + * Build DataTable class. + * + * @param QueryBuilder $query Results from query() method. + * @return \Yajra\DataTables\EloquentDataTable + */ + public function dataTable(QueryBuilder $query): EloquentDataTable + { + return (new EloquentDataTable($query))->setRowId('id'); + } + + /** + * Get query source of dataTable. + * + * @param \App\Models\User $model + * @return \Illuminate\Database\Eloquent\Builder + */ + public function query(User $model): QueryBuilder + { + return $model->newQuery(); + } + + /** + * Optional method if you want to use html builder. + * + * @return \Yajra\DataTables\Html\Builder + */ + public function html(): HtmlBuilder + { + return $this->builder() + ->setTableId('users-table') + ->columns($this->getColumns()) + ->minifiedAjax() + ->orderBy(1) + ->selectStyleSingle() + ->editors([ + Editor::make() + ->fields([ + Fields\Text::make('name'), + Fields\Text::make('email'), + ]), + ]) + ->buttons([ + Button::make('create')->editor('editor'), + Button::make('edit')->editor('editor'), + Button::make('remove')->editor('editor'), + Button::make('excel'), + Button::make('csv'), + Button::make('pdf'), + Button::make('print'), + Button::make('reset'), + Button::make('reload'), + ]); + } + + /** + * Get the dataTable columns definition. + * + * @return array + */ + public function getColumns(): array + { + return [ + Column::make('id'), + Column::make('name'), + Column::make('email'), + Column::make('created_at'), + Column::make('updated_at'), + ]; + } + + /** + * Get filename for export. + * + * @return string + */ + protected function filename(): string + { + return 'Users_'.date('YmdHis'); + } +} +``` + +## Create Editor Class to handle CRUD actions. + +```sh +php artisan datatables:editor Users +``` + +## Register Editor Route + +Edit `routes/web.php` and register the store user route. + +```php +Route::get('/users', [App\Http\Controllers\UsersController::class, 'index'])->name('users.index'); +Route::post('/users', [App\Http\Controllers\UsersController::class, 'store'])->name('users.store'); +``` + +## Update users controller + +```php +namespace App\Http\Controllers; + +use Illuminate\Http\Request; +use App\DataTables\UsersDataTable; +use App\DataTables\UsersDataTableEditor; + +class UsersController extends Controller +{ + public function index(UsersDataTable $dataTable) + { + return $dataTable->render('users.index'); + } + + public function store(UsersDataTableEditor $editor) + { + return $editor->process(request()); + } +} +``` + +## See your editor in action. diff --git a/editor-usage.md b/editor-usage.md new file mode 100644 index 0000000..ea02189 --- /dev/null +++ b/editor-usage.md @@ -0,0 +1,56 @@ +# Using DataTables Editor + +All actions requested by DataTables Editor are being submitted via `POST` ajax request. +This means, that we need to create a `post` request route that will handle all the actions we need. + +> This doc assumes that you are already knowlegeable of [DataTables Editor](https://editor.datatables.net/examples/index) library. + + +## Create your Editor + +You can create your editor using [artisan command](/docs/{{package}}/{{version}}/editor-command). + +```bash +php artisan datatables:editor Users +``` + + +## Setup Editor Model + +See [editor model](/docs/{{package}}/{{version}}/editor-model) docs for ref: + + +## Setup Editor Rules + +See [editor rules](/docs/{{package}}/{{version}}/editor-rules) docs for ref: + + +## Register Route Handler + +```php +use App\DataTables\UsersDataTablesEditor; + +Route::post('editor', function(UsersDataTablesEditor $editor) { + return $editor->process(request()); +}); +``` + + +## Setup AJAX csrf-token + +Since actions are being sent via `post`, we need to make sure that we setup [csrf-token](https://laravel.com/docs/csrf#csrf-x-csrf-token). +Just add the snippets below before your scripts to avoid csrf errors: + +```js +$.ajaxSetup({ + headers: { + 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') + } +}); +``` + + +## Setup your content + +You can use [DataTables Editor Generator](https://editor.datatables.net/generator/index) to help you speed-up the process. +Once generated, copy the necessary scripts and html on your blade template. diff --git a/engine-collection.md b/engine-collection.md index 9aea44b..418ccc4 100644 --- a/engine-collection.md +++ b/engine-collection.md @@ -1,13 +1,13 @@ # Collection Data Source You may use Laravel's Collection as data source for your dataTables. -You can look at `Yajra\Datatables\Enginges\CollectionEngine` class which handles the conversion of your Collection into a readbale DataTable API response. +You can look at `Yajra\DataTables\CollectionDataTable` class which handles the conversion of your Collection into a readable DataTable API response. ## Collection via Factory ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $collection = collect([ @@ -16,7 +16,7 @@ Route::get('user-data', function() { ['id' => 3, 'name' => 'James'], ]); - return Datatables::of($collection)->make(true); + return DataTables::of($collection)->toJson(); }); ``` @@ -24,7 +24,7 @@ Route::get('user-data', function() { ## Collection via Facade ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $collection = collect([ @@ -33,7 +33,7 @@ Route::get('user-data', function() { ['id' => 3, 'name' => 'James'], ]); - return Datatables::queryBuilder($collection)->make(true); + return DataTables::collection($collection)->toJson(); }); ``` @@ -41,16 +41,16 @@ Route::get('user-data', function() { ## Collection via Dependency Injection ```php -use Yajra\Datatables\Datatables; +use Yajra\DataTables\DataTables; -Route::get('user-data', function(Datatables $datatables) { +Route::get('user-data', function(DataTables $dataTables) { $collection = collect([ ['id' => 1, 'name' => 'John'], ['id' => 2, 'name' => 'Jane'], ['id' => 3, 'name' => 'James'], ]); - return $datatables->queryBuilder($collection)->make(true); + return $dataTables->collection($collection)->toJson(); }); ``` @@ -65,6 +65,18 @@ Route::get('user-data', function() { ['id' => 3, 'name' => 'James'], ]); - return app('datatables')->queryBuilder($collection)->make(true); + return app('datatables')->collection($collection)->toJson(); }); ``` + + +## CollectionDataTable new Instance + +```php +use Yajra\DataTables\CollectionDataTable; + +Route::get('user-data', function() { + $collection = App\User::all(); + + return (new CollectionDataTable($collection))->toJson(); +}); diff --git a/engine-eloquent.md b/engine-eloquent.md index baafbc2..f68e4d0 100644 --- a/engine-eloquent.md +++ b/engine-eloquent.md @@ -1,18 +1,18 @@ # Eloquent Data Source You may use Laravel's Eloquent Model as data source for your dataTables. -You can look at `Yajra\Datatables\Enginges\EloquentEngine` class which handles the conversion of your Eloquent Model into a readbale DataTable API response. +You can look at `Yajra\DataTables\EloquentDataTable` class which handles the conversion of your Eloquent Model into a readable DataTable API response. ## Eloquent via Factory ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::of($model)->make(true); + return DataTables::of($model)->toJson(); }); ``` @@ -20,12 +20,12 @@ Route::get('user-data', function() { ## Eloquent via Facade ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model)->make(true); + return DataTables::eloquent($model)->toJson(); }); ``` @@ -33,21 +33,34 @@ Route::get('user-data', function() { ## Eloquent via Dependency Injection ```php -use Yajra\Datatables\Datatables; +use Yajra\DataTables\DataTables; -Route::get('user-data', function(Datatables $datatables) { +Route::get('user-data', function(DataTables $dataTables) { $model = App\User::query(); - return $datatables->eloquent($model)->make(true); + return $dataTables->eloquent($model)->toJson(); }); ``` ## Eloquent via IoC ```php +Route::get('user-data', function() { + $model = App\User::query(); + + return app('datatables')->eloquent($model)->toJson(); +}); +``` + + +## EloquentDataTable new Instance + +```php +use Yajra\DataTables\EloquentDataTable; + Route::get('user-data', function() { $model = App\User::query(); - return app('datatables')->eloquent($model)->make(true); + return (new EloquentDataTable($model))->toJson(); }); ``` diff --git a/engine-query.md b/engine-query.md index e013a70..e800e53 100644 --- a/engine-query.md +++ b/engine-query.md @@ -1,19 +1,19 @@ # Query Builder Data Source You may use Laravel's Query Builder as data source for your dataTables. -You can look at `Yajra\Datatables\Enginges\QueryBuilderEngine` class which handles the conversion of your Query Builder into a readbale DataTable API response. +You can look at `Yajra\DataTables\QueryDataTable` class which handles the conversion of your Query Builder into a readable DataTable API response. ## Query Builder via Factory ```php use DB; -use Datatables; +use DataTables; Route::get('user-data', function() { $query = DB::table('users'); - return Datatables::of($query)->make(true); + return DataTables::of($query)->toJson(); }); ``` @@ -22,12 +22,12 @@ Route::get('user-data', function() { ```php use DB; -use Datatables; +use DataTables; Route::get('user-data', function() { $query = DB::table('users'); - return Datatables::queryBuilder($query)->make(true); + return DataTables::queryBuilder($query)->toJson(); }); ``` @@ -36,12 +36,12 @@ Route::get('user-data', function() { ```php use DB; -use Yajra\Datatables\Datatables; +use Yajra\DataTables\DataTables; -Route::get('user-data', function(Datatables $datatables) { +Route::get('user-data', function(DataTables $dataTables) { $query = DB::table('users'); - return $datatables->queryBuilder($query)->make(true); + return $dataTables->queryBuilder($query)->toJson(); }); ``` @@ -53,6 +53,18 @@ use DB; Route::get('user-data', function() { $query = DB::table('users'); - return app('datatables')->queryBuilder($query)->make(true); + return app('datatables')->queryBuilder($query)->toJson(); }); ``` + + +## QueryDataTable new Instance + +```php +use Yajra\DataTables\QueryDataTable; + +Route::get('user-data', function() { + $query = DB::table('users'); + + return (new QueryDataTable($query))->toJson(); +}); diff --git a/error-handler.md b/error-handler.md new file mode 100644 index 0000000..6ff5ab2 --- /dev/null +++ b/error-handler.md @@ -0,0 +1,79 @@ +# Error Handler + +Laravel DataTables allows you to configure how you want to handle server-side errors when processing your request. +Below are the options available for error handling. + +## ERROR CONFIGURATIONS +Configuration is located at `config/datatables.php` under `error` key. +You can also configure via env by setting `DATATABLES_ERROR` key appropriately. + +The default configuration is `env('DATATABLES_ERROR', null)`. + + +- [NULL](#null-error) : `'error' => null` +- [THROW](#throw-error) : `'error' => 'throw'` +- [CUSTOM MESSAGE](#custom-message) : `'error' => 'Any custom friendly message'` +- [TRANSLATION](#custom-message) : `'error' => 'translation.key'` + + +## NULL Error +If set to `null`, the actual exception message will be used on error response. + +```json +{ + "draw": 24, + "recordsTotal": 200, + "recordsFiltered": 0, + "data": [], + "error": "Exception Message:\n\nSQLSTATE[42S22]: Column not found: 1054 Unknown column 'xxx' in 'order clause' (SQL: select * from `users` where `users`.`deleted_at` is null order by `xxx` asc limit 10 offset 0)" +} +``` + + +## THROW Error +If set to `'throw'`, the package will throw a `\Yajra\DataTables\Exception`. +You can then use your custom error handler if needed. + +**Example Error Handler** + +Update `app\Exceptions\Handler.php` and register dataTables error exception handler. + +```php + /** + * Render an exception into an HTTP response. + * + * @param \Illuminate\Http\Request $request + * @param \Exception $exception + * @return \Illuminate\Http\Response + */ + public function render($request, Exception $exception) + { + if ($exception instanceof \Yajra\DataTables\Exception) { + return response([ + 'draw' => 0, + 'recordsTotal' => 0, + 'recordsFiltered' => 0, + 'data' => [], + 'error' => 'Laravel Error Handler', + ]); + } + + return parent::render($request, $exception); + } +``` + + +## Custom Message +If set to `'any custom message'` or `'translation.key'`, this message will be used when an error occurs when processing the request. + +```json +{ + "draw": 24, + "recordsTotal": 200, + "recordsFiltered": 0, + "data": [], + "error": "any custom message" +} +``` + + diff --git a/export-column.md b/export-column.md new file mode 100644 index 0000000..0295ad8 --- /dev/null +++ b/export-column.md @@ -0,0 +1,23 @@ +# Export Columns + +You can export a column customised header if manually set. + + +## Export Columns with Custom Title + +```php +protected $exportColumns = [ + ['data' => 'name', 'title' => 'Name'], + ['data' => 'email', 'title' => 'Registered Email'], +]; +``` + + +## Export Columns + +```php +protected $exportColumns = [ + 'name', + 'email', +]; +``` \ No newline at end of file diff --git a/exports-installation.md b/exports-installation.md new file mode 100644 index 0000000..79dd9fa --- /dev/null +++ b/exports-installation.md @@ -0,0 +1,30 @@ +# Export Plugin Installation + +Github: https://github.com/yajra/laravel-datatables-export + +This package is a plugin of Laravel DataTables for handling server-side exporting using Queue, OpenSpout and Livewire. + +## Quick Installation + +``` +composer require yajra/laravel-datatables-export -W +``` + +The package also requires batch job: + +``` +php artisan queue:batches-table +php artisan migrate +``` + +## Service Provider (Optional since Laravel 5.5+) + +``` +Yajra\DataTables\ExportServiceProvider::class +``` + +## Configuration and Assets (Optional) + +``` +$ php artisan vendor:publish --tag=datatables-export --force +``` \ No newline at end of file diff --git a/exports-options.md b/exports-options.md new file mode 100644 index 0000000..895d397 --- /dev/null +++ b/exports-options.md @@ -0,0 +1,98 @@ +# Export Options + +## Export Type + +You can set the export type by setting the property to `csv` or `xlsx`. Default value is `xlsx`. + +```php + + +``` + +## Set Excel Sheet Name + +Option 1: You can set the Excel sheet name by setting the property. + +```php + +``` + +Option 2: You can also set the Excel sheet name by overwriting the method. + +```php +protected function sheetName() : string +{ + return "Yearly Report"; +} +``` + +## Formatting Columns + +You can format the column by setting it via Column definition on you DataTable service class. + +```php +Column::make('mobile')->exportFormat('00000000000'), +``` + +The format above will treat mobile numbers as text with leading zeroes. + +## Numeric Fields Formatting + +The package will auto-detect numeric fields and can be used with custom formats. + +```php +Column::make('total')->exportFormat('0.00'), +Column::make('count')->exportFormat('#,##0'), +Column::make('average')->exportFormat('#,##0.00'), +``` + +## Date Fields Formatting + +The package will auto-detect date fields when used with a valid format or is a DateTime instance. + +```php +Column::make('report_date')->exportFormat('mm/dd/yyyy'), +Column::make('created_at'), +Column::make('updated_at')->exportFormat(NumberFormat::FORMAT_DATE_DATETIME), +``` + +## Valid Date Formats + +Valid date formats can be adjusted on `datatables-export.php` config file. + +```php + 'date_formats' => [ + 'mm/dd/yyyy', + NumberFormat::FORMAT_DATE_DATETIME, + NumberFormat::FORMAT_DATE_YYYYMMDD, + NumberFormat::FORMAT_DATE_XLSX22, + NumberFormat::FORMAT_DATE_DDMMYYYY, + NumberFormat::FORMAT_DATE_DMMINUS, + NumberFormat::FORMAT_DATE_DMYMINUS, + NumberFormat::FORMAT_DATE_DMYSLASH, + NumberFormat::FORMAT_DATE_MYMINUS, + NumberFormat::FORMAT_DATE_TIME1, + NumberFormat::FORMAT_DATE_TIME2, + NumberFormat::FORMAT_DATE_TIME3, + NumberFormat::FORMAT_DATE_TIME4, + NumberFormat::FORMAT_DATE_TIME5, + NumberFormat::FORMAT_DATE_TIME6, + NumberFormat::FORMAT_DATE_TIME7, + NumberFormat::FORMAT_DATE_XLSX14, + NumberFormat::FORMAT_DATE_XLSX15, + NumberFormat::FORMAT_DATE_XLSX16, + NumberFormat::FORMAT_DATE_XLSX17, + NumberFormat::FORMAT_DATE_YYYYMMDD2, + NumberFormat::FORMAT_DATE_YYYYMMDDSLASH, + ] +``` + +## Force Numeric Field As Text Format + +Option to force auto-detected numeric value as text format. + +```php +Column::make('id')->exportFormat('@'), +Column::make('id')->exportFormat(NumberFormat::FORMAT_GENERAL), +Column::make('id')->exportFormat(NumberFormat::FORMAT_TEXT), +``` diff --git a/exports-purge.md b/exports-purge.md new file mode 100644 index 0000000..ee246f1 --- /dev/null +++ b/exports-purge.md @@ -0,0 +1,9 @@ +# Export Usage + +## Purging exported files + +On `app\Console\Kernel.php`, register the purge command + +```php +$schedule->command('datatables:purge-export')->weekly(); +``` diff --git a/exports-usage.md b/exports-usage.md new file mode 100644 index 0000000..f5d6a29 --- /dev/null +++ b/exports-usage.md @@ -0,0 +1,24 @@ +# Export Usage + +## Usage + +1. Add the export-button livewire component on your view file that uses dataTable class. + +```php + +``` + +2. On your `DataTable` class, use `WithExportQueue` + +```php +use Yajra\DataTables\WithExportQueue; + +class PermissionsDataTable extends DataTable +{ + use WithExportQueue; + + ... +} +``` + +3. Run your queue worker. Ex: `php artisan queue:work` diff --git a/filter-column.md b/filter-column.md index eb1c2a7..a0e9f88 100644 --- a/filter-column.md +++ b/filter-column.md @@ -4,7 +4,7 @@ In some cases, we need to implement a custom search for a specific column. To achieve this, you can use `filterColumn` api. ```php -use Datatables; +use DataTables; use DB; Route::get('user-data', function() { @@ -16,11 +16,11 @@ Route::get('user-data', function() { 'updated_at', ]); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->filterColumn('fullname', function($query, $keyword) { $sql = "CONCAT(users.first_name,'-',users.last_name) like ?"; $query->whereRaw($sql, ["%{$keyword}%"]); }) - ->make(true); + ->toJson(); }); ``` diff --git a/fractal-installation.md b/fractal-installation.md new file mode 100644 index 0000000..e210f6b --- /dev/null +++ b/fractal-installation.md @@ -0,0 +1,26 @@ +# Fractal Plugin Installation + +Github: https://github.com/yajra/laravel-datatables-fractal + +Run the following command in your project to get the latest version of the plugin: + +`composer require yajra/laravel-datatables-fractal:^9.0` + +## Configuration +> This step is optional if you are using Laravel 5.5 + +Open the file ```config/app.php``` and then add following service provider. + +```php +'providers' => [ + // ... + Yajra\DataTables\DataTablesServiceProvider::class, + Yajra\DataTables\FractalServiceProvider::class, +], +``` + +After completing the step above, use the following command to publish configuration & assets: + +``` +php artisan vendor:publish --tag=datatables-fractal --force +``` diff --git a/general-settings.md b/general-settings.md index ac41cfc..358bb25 100644 --- a/general-settings.md +++ b/general-settings.md @@ -37,7 +37,7 @@ The sql generated will be like `column LIKE "%k%e%y%w%o%r%d%"` when set to `true DataTables internal index id response column name. ```php -'index_column' => 'DT_Row_Index', +'index_column' => 'DT_RowIndex', ``` @@ -47,9 +47,9 @@ This is where you can register your custom datatables engine. ```php 'engines' => [ - 'eloquent' => Yajra\Datatables\Engines\EloquentEngine::class, - 'query' => Yajra\Datatables\Engines\QueryBuilderEngine::class, - 'collection' => Yajra\Datatables\Engines\CollectionEngine::class, + 'eloquent' => Yajra\DataTables\Engines\EloquentEngine::class, + 'query' => Yajra\DataTables\Engines\QueryBuilderEngine::class, + 'collection' => Yajra\DataTables\Engines\CollectionEngine::class, // add your custom engine ], ``` @@ -83,4 +83,22 @@ Default fractal serializer to be used when serializing the response. ```php 'serializer' => League\Fractal\Serializer\DataArraySerializer::class, ``` + +## Script Template +DataTables html builder script blade template. +If published, the file will installed on `resources/views/vendor/datatables/script.blade.php`. + +```php +'script_template' => 'datatables::script', +``` + + +## NULLS LAST sql +Nulls last sql pattern for Postgresql & Oracle. + +> {tip} For MySQL, use '-%s %s' as the sql pattern. + +```php +'nulls_last_sql' => '%s %s NULLS LAST', +``` diff --git a/html-builder-additional-scripts.md b/html-builder-additional-scripts.md new file mode 100644 index 0000000..c8a4dc1 --- /dev/null +++ b/html-builder-additional-scripts.md @@ -0,0 +1,24 @@ +# Additional JavaScript Scripts + +## General Usage + +Starting with v10.10.0, you can easily add additional JavaScript scripts as blade views in your `html` function like this: + +```php +return $this->builder() + ->addScript('your.view.name'); +``` + +## Built-in Additional Scripts + +### Scout Search + +**View:** `datatables::scout` + +Control visibility of sort icons on the frontend table. Hide sort icons when Scout Search is successful (indicating fixed ordering by search relevance) and show them again when the search keyword is removed. + +### Batch Remove Optimization + +**View:** `datatables::functions.batch_remove` + +Delete all unnecessary information before sending `remove` requests (Editor), keeping only the `DT_RowId`. Otherwise, batch remove requests may fail because of server limits. diff --git a/html-builder-ajax.md b/html-builder-ajax.md index 3954330..92424d5 100644 --- a/html-builder-ajax.md +++ b/html-builder-ajax.md @@ -20,7 +20,7 @@ When the attribute passed is a `string`. The builder will treat this as the `URL $builder->ajax(route('users.data')); ``` -> {tip} Setting ajax to `null` or `empty string` will use the current url where Datatables was used. +> {tip} Setting ajax to `null` or `empty string` will use the current url where DataTables was used. **Array Attributes** diff --git a/html-builder-callbacks.md b/html-builder-callbacks.md index 1e78d93..b48b3fc 100644 --- a/html-builder-callbacks.md +++ b/html-builder-callbacks.md @@ -18,4 +18,13 @@ You can use a `js` string for each valid callback as documented on [`datatables. |`stateLoaded` | State loaded callback. | |`stateLoadParams` | State loaded - data manipulation callback | |`stateSaveCallback` | Callback that defines how the table state is stored and where. | -|`stateSaveParams` | State save - data manipulation callbac | +|`stateSaveParams` | State save - data manipulation callback | + +## Example +In this example, we will hook on the the `drawCallback` of dataTable. + +```php +$builder->parameters([ + 'drawCallback' => 'function() { alert("Table Draw Callback") }', +]); +``` \ No newline at end of file diff --git a/html-builder-column-builder.md b/html-builder-column-builder.md new file mode 100644 index 0000000..ddaff77 --- /dev/null +++ b/html-builder-column-builder.md @@ -0,0 +1,39 @@ +# Html Builder - Column Builder + +Column Builder is a fluent class that we can use to build our columns. + + +## Upgrading Your Existing Column Definitions + +### FROM + +```php +$column = [ + 'name' => 'id', + 'data' => 'id', + 'title' => 'Id', + 'searchable' => true, + 'orderable' => true, + 'render' => 'function(){}', + 'footer' => 'Id', + 'exportable' => true, + 'printable' => true, +]; +``` + +### TO + +```php +use Yajra\DataTables\Html\Column; + +$column = Column::make('id') + ->title('Id') + ->searchable(true) + ->orderable(true) + ->render('\'
\' + (full[\'deleted_at\'] == null ? \'Active\' : \'Inactive\') + \'
\';\'\'' ) + ->exportRender(function($row,$data){return $data == 1 ? 'Active' : 'Inactive'}) + ->footer('Id') + ->exportable(true) + ->printable(true); +``` + diff --git a/html-builder-column.md b/html-builder-column.md index 162c0d8..f0a2b03 100644 --- a/html-builder-column.md +++ b/html-builder-column.md @@ -26,7 +26,7 @@ You also need to look at [`datatables.net`](https://datatables.net/reference/opt ### Name (Optional) Name attribute represents the `column` name from your data source. -Datatables will use this attribute when performing search and ordering functions. +DataTables will use this attribute when performing search and ordering functions. > {tip} If not set, `name` attribute will automatically be set to same value as `data` attribute. @@ -47,6 +47,10 @@ Orderable attribute will toggle the `ordering` ability for the defined column. D ### Render (Optional) Render attribute is a `js` script string that you can use to modify the way the column is being rendered via `javascript`. +### Export Render (Optional) +Export Render attribute is a `php callback function` that you can use to modify the way the column is being rendered via `print` or `export (CSV/Excel/PDF)`. + + ### Footer (Optional) Footer attribute will be as your `tables` column's `footer` content ``. @@ -55,9 +59,9 @@ Footer attribute will be as your `tables` column's `footer` content ` Exportable attribute should be used with the [Buttons Plugin](/docs/laravel-datatables/{{version}}/buttons-installation) +> Exportable attribute should be used with the [Buttons Plugin](/docs/{{package}}/{{version}}/buttons-installation) ### Printable (Optional) Printable attribute will flag the column to be included when `printing` the table. Default value is `true`. -> Exportable attribute should be used with the [Buttons Plugin](/docs/laravel-datatables/{{version}}/buttons-installation) +> Exportable attribute should be used with the [Buttons Plugin](/docs/{{package}}/{{version}}/buttons-installation) diff --git a/html-builder-config.md b/html-builder-config.md new file mode 100644 index 0000000..b851797 --- /dev/null +++ b/html-builder-config.md @@ -0,0 +1,16 @@ +# Html Builder Config + +Default table attributes are now configurable. +To begin, you need to publish the config by running `php artisan vendor:publish --tag=datatables-html` + +Published config is located at `config/datatables-html.php`. +You can then update the default table attributes that you prefer for every table rendered using the builder class. + +```php +return [ + 'table' => [ + 'class' => 'table', + 'id' => 'dataTableId' + ] +]; +``` \ No newline at end of file diff --git a/html-builder-index.md b/html-builder-index.md index b29845f..79ecaaa 100644 --- a/html-builder-index.md +++ b/html-builder-index.md @@ -7,8 +7,8 @@ The default attributes of index column are: ```php [ 'defaultContent' => '', - 'data' => 'DT_Row_Index', - 'name' => 'DT_Row_Index', + 'data' => 'DT_RowIndex', + 'name' => 'DT_RowIndex', 'title' => '', 'render' => null, 'orderable' => false, @@ -19,4 +19,4 @@ The default attributes of index column are: ]; ``` -The `addIndex` api should be used along with [`addIndexColumn`](/docs/laravel-datatables/{{version}}/index-column) of `Datatables`. \ No newline at end of file +The `addIndex` api should be used along with [`addIndexColumn`](/docs/{{package}}/{{version}}/index-column) of `DataTables`. diff --git a/html-builder-macro.md b/html-builder-macro.md new file mode 100644 index 0000000..e7f4ce4 --- /dev/null +++ b/html-builder-macro.md @@ -0,0 +1,31 @@ +# Html Builder Macro + +You can extend DataTables HTML Builder using `macro`. + +## Example macro: +```php +use Yajra\DataTables\Html\Builder; +use Yajra\DataTables\Html\Column; + +Builder::macro('addEditColumn', function () { + $attributes = [ + 'title' => 'Edit', + 'data' => 'edit', + 'name' => '', + 'orderable' => false, + 'searchable' => false, + ]; + + $this->collection->push(new Column($attributes)); + + return $this; +}); + +``` + +## Usage +```php +$builder = new Builder; +$builder->addEditColumn()->ajax()->parameters([]); + +``` diff --git a/html-builder-minified-ajax.md b/html-builder-minified-ajax.md new file mode 100644 index 0000000..20a529e --- /dev/null +++ b/html-builder-minified-ajax.md @@ -0,0 +1,26 @@ +# Html Builder Minified Ajax + +Ajax is an option that you set to tell `dataTable` where to fetch it's data. +But unlike the regular ajax method, `minifiedAjax` minifies the url generated by dataTables by removing any unnecessary query parameters thus shortening the url +from approx 1500 url length down to 500. +Shortening the URL will help us prevent any browser and development issues concerning the URL length exceeding the max allowed value. + + +**Syntax** +```php +$builder->minifiedAjax($url, $script = '', $data = []); +``` + +## Ajax Parameters +`$url` is the url where we will fetch our json data. + +`$script` any vanilla javascript to be included on `data` method of ajax. + +`$data` is an array of values to be appended on server request. + + +```php +$builder->minifiedAjax('', null, ['foo' => 'bar']) +``` + + diff --git a/html-builder-parameters.md b/html-builder-parameters.md index 356b1b9..cd60c84 100644 --- a/html-builder-parameters.md +++ b/html-builder-parameters.md @@ -3,3 +3,17 @@ Parameters are basically the options you pass when declaring your `DataTable` js script. See the [`datatables.net`](https://datatables.net) official documentation for the list of all possible [`options`](https://datatables.net/reference/option/). + + +## Example +```php +$builder->parameters([ + 'paging' => true, + 'searching' => true, + 'info' => false, + 'searchDelay' => 350, + 'language' => [ + 'url' => url('js/dataTables/language.json') + ], +]); +``` \ No newline at end of file diff --git a/html-builder-post-ajax.md b/html-builder-post-ajax.md new file mode 100644 index 0000000..ec672d7 --- /dev/null +++ b/html-builder-post-ajax.md @@ -0,0 +1,35 @@ +# Html Builder Post Ajax + +Use post method to submit the dataTables ajax request. + +See [datatables.net](https://datatables.net/) official documentation for [`ajax option`](https://datatables.net/reference/option/ajax) for details. + +**Syntax** +```php +$builder->postAjax($attributes); +``` + +## Post Ajax Parameter +Ajax parameter (`$attributes`) can either be a string or an array. + +**String Attributes** + +When the attribute passed is a `string`. The builder will treat this as the `URL` where we fetch our data. + +```php +$builder->postAjax(route('users.data')); +``` + +> {tip} Setting ajax to `null` or `empty string` will use the current url where DataTables was used. + +**Array Attributes** + +Attributes are the same with the `ajax()` method request valid parameters. + +```php +$builder->postAjax([ + 'url' => route('users.data'), +]) +``` + + diff --git a/html-builder-table.md b/html-builder-table.md index 44c2db8..285a6da 100644 --- a/html-builder-table.md +++ b/html-builder-table.md @@ -8,12 +8,12 @@ Table api accepts two parameters: `$builder->table(array $attributes, $footer = ## Table Example with Footer ```php -use Datatables; -use Yajra\Datatables\Html\Builder; +use DataTables; +use Yajra\DataTables\Html\Builder; Route::get('users', function(Builder $builder) { if (request()->ajax()) { - return Datatables::of(User::query())->make(true); + return DataTables::of(User::query())->toJson(); } $html = $builder->columns([ @@ -21,7 +21,7 @@ Route::get('users', function(Builder $builder) { ['data' => 'name', 'footer' => 'Name'], ['data' => 'email', 'footer' => 'Email'], ['data' => 'created_at', 'footer' => 'Created At'], - ['data' => 'updated_at', 'footer' => 'Updated At'), + ['data' => 'updated_at', 'footer' => 'Updated At'], ]); return view('users.index', compact('html')); @@ -34,7 +34,7 @@ On your `resources/views/users/index.blade.php`. @extends('app') @section('contents') - {!! $html->table(['class' => 'table table-bordered', true]) !!} +    {!! $html->table(['class' => 'table table-bordered'], true) !!} @endsection @push('scripts') diff --git a/html-builder.md b/html-builder.md index 3b663c2..4339798 100644 --- a/html-builder.md +++ b/html-builder.md @@ -1,6 +1,6 @@ # Html Builder -Datatables has a built-in html builder that you can use to automatically generate your table mark-up and javascripts declarations. +DataTables has a built-in html builder that you can use to automatically generate your table mark-up and javascripts declarations. ## Html Builder via Dependency Injection @@ -8,9 +8,10 @@ Datatables has a built-in html builder that you can use to automatically generat You can use the `Builder` class by using Dependency Injection. ```php -use Yajra\Datatables\Html\Builder; +use Yajra\DataTables\Html\Builder; Route::get('users', function(Builder $builder) { + // }); ``` @@ -24,12 +25,12 @@ Route::get('users', function() { ``` -## Html Builder from Datatables instance +## Html Builder from DataTables instance ```php -use Yajra\Datatables\Datatables; +use Yajra\DataTables\DataTables; -Route::get('users', function(Datatables $dataTable) { +Route::get('users', function(DataTables $dataTable) { $builder = $dataTable->getHtmlBuilder(); }); ``` @@ -37,37 +38,38 @@ Route::get('users', function(Datatables $dataTable) { ## Html Builder Example -```php -use Datatables; -use Yajra\Datatables\Html\Builder; +```php filename=routes/web.php +use Yajra\DataTables\Facades\DataTables; +use Yajra\DataTables\Html\Builder; +use Yajra\DataTables\Html\Column; +use App\Models\User; Route::get('users', function(Builder $builder) { - if (request()->ajax()) { - return Datatables::of(User::query())->make(true); + if (request()->ajax()) { + return DataTables::of(User::query())->toJson(); } - $html = $builder->columns([ - ['data' => 'id', 'name' => 'id', 'title' => 'Id'], - ['data' => 'name', 'name' => 'name', 'title' => 'Name'], - ['data' => 'email', 'name' => 'email', 'title' => 'Email'], - ['data' => 'created_at', 'name' => 'created_at', 'title' => 'Created At'], - ['data' => 'updated_at', 'name' => 'updated_at', 'title' => 'Updated At']), - ]); + $html = $builder->columns([ + Column::make('id'), + Column::make('name'), + Column::make('email'), + Column::make('created_at'), + Column::make('updated_at'), + ]); - return view('users.index', compact('html')); + return view('users.index', compact('html')); }); ``` -On your `resources/views/users/index.blade.php`. -```php +```php filename=resources/views/users/index.blade.php @extends('app') @section('contents') - {!! $html->table() !!} + {{ $html->table() }} @endsection @push('scripts') - {!! $html->scripts() !!} + {{ $html->scripts() }} @endpush ``` diff --git a/html-installation.md b/html-installation.md new file mode 100644 index 0000000..f616b7e --- /dev/null +++ b/html-installation.md @@ -0,0 +1,29 @@ +# HTML Builder Plugin + +## Installation + +Github: https://github.com/yajra/laravel-datatables-html + +Run the following command in your project to get the latest version of the plugin: + +`composer require yajra/laravel-datatables-html:^10.0` + +## Configuration + +> This step is optional if you are using Laravel 5.5 + +Open the file ```config/app.php``` and then add following service provider. + +```php +'providers' => [ + // ... + Yajra\DataTables\DataTablesServiceProvider::class, + Yajra\DataTables\HtmlServiceProvider::class, +], +``` + +After completing the step above, use the following command to publish configuration & assets: + +``` +php artisan vendor:publish --tag=datatables-html +``` diff --git a/index-column.md b/index-column.md index 0df994d..0afb93a 100644 --- a/index-column.md +++ b/index-column.md @@ -4,16 +4,32 @@ In some cases, you need to track the index of the records on your response. To achieve this, you can add an index column on your response by using `addIndexColumn` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->addIndexColumn() - ->make(true); + ->toJson(); }); ``` -Using `addIndexColumn` will add another column on your response with a column name that is set on [`index_column`](/docs/laravel-datatables/{{version}}/general-settings#index-column) configuration. -The default index column name is `DT_Row_Index` \ No newline at end of file +Using `addIndexColumn` will add another column on your response with a column name that is set on [`index_column`](/docs/{{package}}/{{version}}/general-settings#index-column) configuration. +The default index column name is `DT_RowIndex`. + +If you want to customize the index used by the `DT_RowIndex`, you can use `setRowId('COLUMN')` to change the index number. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->setRowId('id') + ->toJson(); +}); +``` + +Be careful with this option, an index should be unique and an integer to be useful for DataTables. diff --git a/installation.md b/installation.md index 40d2b94..992bbba 100644 --- a/installation.md +++ b/installation.md @@ -2,7 +2,7 @@ - [Installation](#installation) - [Requirements](#requirements) - - [Installing Laravel-Datatables](#installing-laravel-datatables-oracle) + - [Installing Laravel-DataTables](#installing-laravel-datatables) - [Configuration](#configuration) @@ -11,30 +11,44 @@ ### Requirements -- [PHP >=5.5.9](http://php.net/) -- [Laravel 5.x](https://github.com/laravel/framework) +- [Laravel 9|10](https://github.com/laravel/framework) - [jQuery DataTables v1.10.x](http://datatables.net/) - -### Installing Laravel Datatables + +### Installing Laravel DataTables -Laravel Datatables can be installed with [Composer](http://getcomposer.org/doc/00-intro.md). More details about this package in Composer can be found [here](https://packagist.org/packages/yajra/laravel-datatables-oracle). +Laravel DataTables can be installed with [Composer](http://getcomposer.org/doc/00-intro.md). More details about this package in Composer can be found [here](https://packagist.org/packages/yajra/laravel-datatables-oracle). Run the following command in your project to get the latest version of the package: +```bash +composer require yajra/laravel-datatables-oracle:"^10.3.1" ``` -composer require yajra/laravel-datatables-oracle + +If you are using most of the DataTables plugins like Buttons & Html, you can alternatively use the all-in-one installer package. + +#### Laravel 9 + +```bash +composer require yajra/laravel-datatables:"^9.0" +``` + +#### Laravel 10 + +```bash +composer require yajra/laravel-datatables:^10.0 ``` ### Configuration +> This step is optional if you are using Laravel 5.5+ Open the file ```config/app.php``` and then add following service provider. ```php 'providers' => [ // ... - Yajra\Datatables\DatatablesServiceProvider::class, + Yajra\DataTables\DataTablesServiceProvider::class, ], ``` diff --git a/introduction.md b/introduction.md index dd590b7..aaa9b08 100644 --- a/introduction.md +++ b/introduction.md @@ -1,32 +1,31 @@ # Introduction -## jQuery DataTables API for Laravel + +## Laravel +The PHP Framework For Web Artisans. -[![Join the chat at https://gitter.im/yajra/laravel-datatables](https://badges.gitter.im/yajra/laravel-datatables.svg)](https://gitter.im/yajra/laravel-datatables?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![License](https://poser.pugx.org/yajra/laravel-datatables-oracle/license)](https://packagist.org/packages/yajra/laravel-datatables-oracle) +Laravel is a web application framework with expressive, elegant syntax. +We believe development must be an enjoyable, creative experience to be truly fulfilling. +Laravel attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as: -[![Laravel 4.2|5.x](https://img.shields.io/badge/Laravel-4.2|5.x-orange.svg)](http://laravel.com) -[![Latest Stable Version](https://poser.pugx.org/yajra/laravel-datatables-oracle/v/stable)](https://packagist.org/packages/yajra/laravel-datatables-oracle) -[![Build Status](https://travis-ci.org/yajra/laravel-datatables.svg?branch=master)](https://travis-ci.org/yajra/laravel-datatables) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yajra/laravel-datatables/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yajra/laravel-datatables/?branch=master) -[![Total Downloads](https://poser.pugx.org/yajra/laravel-datatables-oracle/downloads)](https://packagist.org/packages/yajra/laravel-datatables-oracle) +Official documentation of Laravel is available at [laravel.com](https://laravel.com/) -This package is created to handle [server-side](https://www.datatables.net/manual/server-side) works of [DataTables](http://datatables.net) jQuery Plugin via [AJAX option](https://datatables.net/reference/option/ajax) by using Eloquent ORM, Fluent Query Builder or Collection. + +## DataTables +DataTables is a plug-in for the [jQuery](https://jquery.com/) Javascript library. +It is a highly flexible tool, based upon the foundations of progressive enhancement, and will add advanced interaction controls to any HTML table. -```php -use Yajra\Datatables\Facades\Datatables; +Official documentation of DataTables is available at [datatables.net](https://datatables.net) -// Using Eloquent -return Datatables::eloquent(User::query())->make(true); + +## Laravel DataTables + +[![License](https://poser.pugx.org/yajra/laravel-datatables-oracle/license)](https://packagist.org/packages/yajra/laravel-datatables-oracle) + +[![Latest Stable Version](https://poser.pugx.org/yajra/laravel-datatables-oracle/v/stable)](https://packagist.org/packages/yajra/laravel-datatables-oracle) + +[![Total Downloads](https://poser.pugx.org/yajra/laravel-datatables-oracle/downloads)](https://packagist.org/packages/yajra/laravel-datatables-oracle) -// Using Query Builder -return Datatables::queryBuilder(DB::table('users'))->make(true); +Laravel DataTables is a package that handles the [server-side](https://www.datatables.net/manual/server-side) works of [DataTables](http://datatables.net) using [Laravel](http://laravel.com). -// Using Collection -return Datatables::collection(User::all())->make(true); -// Using the Engine Factory -return Datatables::of(User::query())->make(true); -return Datatables::of(DB::table('users'))->make(true); -return Datatables::of(User::all())->make(true); -``` diff --git a/make-hidden.md b/make-hidden.md new file mode 100644 index 0000000..bdf21e0 --- /dev/null +++ b/make-hidden.md @@ -0,0 +1,17 @@ +# Hide attributes from Json + +When you are working with Eloquent Object, you can apply the `makeHidden()` ([Laravel documentation](https://laravel.com/docs/master/eloquent-serialization#hiding-attributes-from-json)) function before converting your object toArray(). + +It can prevent overriding attributes to be compute and increase the performance of converting the object into an array. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::with('posts.comment')->query(); + + return DataTables::eloquent($model) + ->makeHidden('posts') + ->toJson(); +}); +``` diff --git a/manual-order.md b/manual-order.md index c64b98d..3d19851 100644 --- a/manual-order.md +++ b/manual-order.md @@ -1,15 +1,15 @@ # Manual Order -You may optionally disable the default ordering function of Datatables and write you own using `order` api. +You may optionally disable the default ordering function of DataTables and write you own using `order` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->order(function ($query) { if (request()->has('name')) { $query->orderBy('name', 'asc'); @@ -19,6 +19,6 @@ Route::get('user-data', function() { $query->orderBy('email', 'desc'); } }) - ->make(true); + ->toJson(); }); -``` \ No newline at end of file +``` diff --git a/manual-search.md b/manual-search.md index 167c7d6..94fec6c 100644 --- a/manual-search.md +++ b/manual-search.md @@ -7,22 +7,22 @@ To achieve this, you can use the `filter` api. ## Manual Searching without Global Search ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->filter(function ($query) { if (request()->has('name')) { - $query->where('name', 'like', "%{request('name')}%"); + $query->where('name', 'like', "%" . request('name') . "%"); } if (request()->has('email')) { - $query->where('email', 'like', "%{request('email')}%"); + $query->where('email', 'like', "%" . request('email') . "%"); } }) - ->make(true); + ->toJson(); }); ``` @@ -32,21 +32,21 @@ Route::get('user-data', function() { > {tip} To enable global search with filter api, just set the 2nd argument to `true`. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->filter(function ($query) { if (request()->has('name')) { - $query->where('name', 'like', "%{request('name')}%"); + $query->where('name', 'like', "%" . request('name') . "%"); } if (request()->has('email')) { - $query->where('email', 'like', "%{request('email')}%"); + $query->where('email', 'like', "%" . request('email') . "%"); } }, true) - ->make(true); + ->toJson(); }); ``` diff --git a/order-by-nulls-last.md b/order-by-nulls-last.md new file mode 100644 index 0000000..f3f713b --- /dev/null +++ b/order-by-nulls-last.md @@ -0,0 +1,17 @@ +# Order by NULLS LAST + +This api will set DataTables to perform ordering with `NULLS LAST` option. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->orderByNullsLast() + ->toJson(); +}); +``` + +> You must update [nulls_last_sql](/docs/{{package}}/{{version}}/general-settings#nulls-last-sql) config and use a pattern that matches your DB Driver. diff --git a/order-column.md b/order-column.md index 5d19648..6413db8 100644 --- a/order-column.md +++ b/order-column.md @@ -7,13 +7,41 @@ In some cases, you may want to use a custom order sql for a specific column. To In this example, we will order the column name with nulls as last result. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->orderColumn('name', '-name $1') - ->make(true); + ->toJson(); +}); +``` + +Here is another example of orderColumn using closure. + +```php +use DataTables; + +Route::get('user-data', function () { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->orderColumn('name', function ($query, $order) { + $query->orderBy('status', $order); + }); +}); +``` + +Disable ordering via orderColumn. + +```php +use DataTables; + +Route::get('user-data', function () { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->orderColumn('name', false); }); ``` \ No newline at end of file diff --git a/order-columns.md b/order-columns.md index 3fef0f1..aac5ae2 100644 --- a/order-columns.md +++ b/order-columns.md @@ -11,13 +11,13 @@ In some cases, you may want to use a custom order sql for a set of columns. To a In this example, we will order the column name with nulls as last result. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->orderColumns(['name', 'email'], '-:column $1') - ->make(true); + ->toJson(); }); -``` \ No newline at end of file +``` diff --git a/print-column.md b/print-column.md new file mode 100644 index 0000000..5988404 --- /dev/null +++ b/print-column.md @@ -0,0 +1,23 @@ +# Print Column + +You can print a column customised header if manually set. + + +## Print Columns with Custom Title + +```php +protected $printColumns = [ + ['data' => 'name', 'title' => 'Name'], + ['data' => 'email', 'title' => 'Registered Email'], +]; +``` + + +## Print Columns + +```php +protected $printColumns = [ + 'name', + 'email', +]; +``` \ No newline at end of file diff --git a/query-builder.md b/query-builder.md deleted file mode 100644 index daa9c52..0000000 --- a/query-builder.md +++ /dev/null @@ -1,16 +0,0 @@ -# Query Builder Extension - -Datatables instance allows you to proxy a database query call. - -```php -use Datatables; - -Route::get('user-data', function() { - $model = App\User::query(); - - $dataTable = Datatables::eloquent($model); - $dataTable->where('company_id', 2); - - return $dataTable->make(true); -}); -``` \ No newline at end of file diff --git a/quick-starter.md b/quick-starter.md new file mode 100644 index 0000000..15b1c7b --- /dev/null +++ b/quick-starter.md @@ -0,0 +1,266 @@ +# Quick Starter + + +## 01. Installing Laravel & DataTables + +### Quick Installation + +If you have already installed [Laravel Installer](https://laravel.com/docs#your-first-laravel-project) on your local machine, you may create a new project via laravel command: + +```shell +laravel new datatables +``` + +After the project has been created, we will then install [Laravel UI](https://github.com/laravel/ui) and [Yajra DataTables](https://github.com/yajra/laravel-datatables) + +```shell +cd datatables + +composer require laravel/ui --dev +php artisan ui bootstrap --auth + +composer require yajra/laravel-datatables +``` + +For simplicity, you may use SQLite to store your application's data. To instruct Laravel to use SQLite instead of MySQL, update your new application's `.env` file and remove all of the `DB_*` environment variables except for the `DB_CONNECTION` variable, which should be set to `sqlite`: + +```shell +touch database/database.sqlite +``` + +```dotenv filename=.env +DB_CONNECTION=sqlite +``` + + +## 02. Install Laravel DataTables Vite + +Next, we will install [Laravel DataTables Vite](https://github.com/yajra/laravel-datatables-vite) to simplify our frontend setup. + +```shell +npm i laravel-datatables-vite --save-dev +``` + +This will install the following packages: + +``` + - Bootstrap Icons + - DataTables with Buttons and Select plugins for Bootstrap 5 + - Laravel DataTables custom scripts +``` + +Once installed, we can now configure our scripts and css needed for our application. + +```js filename=resources/js/app.js +import './bootstrap'; +import 'laravel-datatables-vite'; +``` + +```postcss filename=resources/sass/app.scss +// Fonts +@import url('https://fonts.bunny.net/css?family=Nunito'); + +// Variables +@import 'variables'; + +// Bootstrap +@import 'bootstrap/scss/bootstrap'; + +// DataTables +@import 'bootstrap-icons/font/bootstrap-icons.css'; +@import "datatables.net-bs5/css/dataTables.bootstrap5.min.css"; +@import "datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css"; +@import 'datatables.net-select-bs5/css/select.bootstrap5.css'; +``` + +We just need to start the Vite development server to automatically recompile our JS, CSS and refresh the browser when we make changes to our Blade templates: + +```shell +npm run dev +``` + + +## 03. Setup a Users DataTable + +Open a new terminal in your `datatables` project directory and run the following command: + +```shell +php artisan datatables:make Users +``` + +Next, we will configure our `UsersDataTable` and add the columns that we want to display. + +```php filename=app/DataTables/UsersDataTable.php +namespace App\DataTables; + +use App\Models\User; +use Illuminate\Database\Eloquent\Builder as QueryBuilder; +use Yajra\DataTables\EloquentDataTable; +use Yajra\DataTables\Html\Builder as HtmlBuilder; +use Yajra\DataTables\Html\Button; +use Yajra\DataTables\Html\Column; +use Yajra\DataTables\Services\DataTable; + +class UsersDataTable extends DataTable +{ + public function dataTable(QueryBuilder $query): EloquentDataTable + { + return (new EloquentDataTable($query))->setRowId('id'); + } + + public function query(User $model): QueryBuilder + { + return $model->newQuery(); + } + + public function html(): HtmlBuilder + { + return $this->builder() + ->setTableId('users-table') + ->columns($this->getColumns()) + ->minifiedAjax() + ->orderBy(1) + ->selectStyleSingle() + ->buttons([ + Button::make('add'), + Button::make('excel'), + Button::make('csv'), + Button::make('pdf'), + Button::make('print'), + Button::make('reset'), + Button::make('reload'), + ]); + } + + public function getColumns(): array + { + return [ + Column::make('id'), + Column::make('name'), + Column::make('email'), + Column::make('created_at'), + Column::make('updated_at'), + ]; + } + + protected function filename(): string + { + return 'Users_'.date('YmdHis'); + } +} +``` + + +## 04. Setup a Users Controller, View & Route + +```shell +php artisan make:controller UsersController +``` + +```php filename=app/Http/Controllers/UsersController.php +namespace App\Http\Controllers; + +use App\DataTables\UsersDataTable; + +class UsersController extends Controller +{ + public function index(UsersDataTable $dataTable) + { + return $dataTable->render('users.index'); + } +} +``` + +```blade filename=resources/views/users/index.blade.php +@extends('layouts.app') + +@section('content') +
+
+
Manage Users
+
+ {{ $dataTable->table() }} +
+
+
+@endsection + +@push('scripts') + {{ $dataTable->scripts(attributes: ['type' => 'module']) }} +@endpush +``` + +```php filename=routes/web.php +use App\Http\Controllers\UsersController; + +Route::get('/users', [UsersController::class, 'index'])->name('users.index'); +``` + +### Use ViteJs / script type defaults to module + +You can also set DataTable to use vitejs by default by registering `Builder::useVite()` inside the `AppServiceProvider`. + +```php +namespace App\Providers; + +use Illuminate\Support\ServiceProvider; +use Yajra\DataTables\Html\Builder; + +class AppServiceProvider extends ServiceProvider +{ + public function boot(): void + { + Builder::useVite(); + } +} +``` + +Upon registering, you can now use scripts and without the need to set the type to module. + +```php +@push('scripts') + {{ $dataTable->scripts() }} +@endpush +``` + + + +## 05. Update the default app layout + +To be able to load our custom scripts, we need to add `@stack('scripts')` before the end of `body` tag in our `app.blade.php` layout. + +```blade filename=resources/views/layouts/app.blade.php +.... +
+ @yield('content') +
+ + @stack('scripts') + + +``` + + +## 06. Migrate and Seed Test Data + +```shell +php artisan migrate +php artisan tinker +``` + +```php +Psy Shell v0.9.9 (PHP 7.2.22 — cli) by Justin Hileman +>>> User::factory(100)->create() +``` + +Our application should now be ready to run. + +```shell +php artisan serve +``` + +Once you have started the Artisan development server, your application will be accessible in your web browser at [http://localhost:8000]([http://localhost:8000). + +We can now visit our [`/users`](http://localhost:8000/users) route and see our users table. + +Laravel DataTables Users diff --git a/raw-columns.md b/raw-columns.md new file mode 100644 index 0000000..bbe0da6 --- /dev/null +++ b/raw-columns.md @@ -0,0 +1,20 @@ +# Raw Columns + +By default, Laravel DataTables protects us from XSS attack by escaping all our outputs. +In cases where you want to render an html content, please use `rawColumns` api. + + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->addColumn('link', 'Html Column') + ->addColumn('action', 'path.to.view') + ->rawColumns(['link', 'action']) + ->toJson(); +}); +``` + diff --git a/readme.md b/readme.md index 9dc60f3..b2985c7 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@ -# Laravel Datatables Documentation +# Laravel DataTables Documentation ## Contribution Guidelines If you are submitting documentation for the **current stable release**, submit it to the corresponding branch. -For example, documentation for Laravel Datatables 5.1 would be submitted to the `5.1` branch. -Documentation intended for the next release of Laravel Datatables should be submitted to the `master` branch. \ No newline at end of file +For example, documentation for Laravel DataTables 6.0 would be submitted to the `6.0` branch. +Documentation intended for the next release of Laravel DataTables should be submitted to the `master` branch. diff --git a/regex.md b/regex.md index 9c5774e..02b1000 100644 --- a/regex.md +++ b/regex.md @@ -1,6 +1,6 @@ # Regex Searching -Datatables has the ability to perform search using regular expressions. +DataTables has the ability to perform search using regular expressions. > Regex search only works and tested on the following Laravel DB drivers: MySQL, SQLite and Oracle. @@ -22,4 +22,4 @@ $('#example').dataTable({ "regex": true } }); -``` \ No newline at end of file +``` diff --git a/relationships.md b/relationships.md new file mode 100644 index 0000000..cccbd46 --- /dev/null +++ b/relationships.md @@ -0,0 +1,56 @@ +# Eager Loading Relationships + +`DataTables` support searching and sorting of eager loaded relationships when using `Eloquent`. +In this example, I will show you how to setup a eager loading search using `EloquentEngine`. + +To enable search, we need to eager load the relationship we intend to use using Laravel's `User::with('posts')` api. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::with('posts'); + + return DataTables::eloquent($model) + ->addColumn('posts', function (User $user) { + return $user->posts->map(function($post) { + return str_limit($post->title, 30, '...'); + })->implode('
'); + }) + ->toJson(); +}); +``` + +To trigger search on `posts` relationship, we need to specify the `relation.column_name` as the `name` attribute in our `javascript` appropriately. + +```php + +``` + +Looking at `{data: 'posts', name: 'posts.title'},`: +- `data: posts` represents the data key (`data.posts`) that we are going to display on our table. +- `name: posts.title` represents the `User` model relationship (`posts`) and the column we are going to perform our search (`title`). + +It is advised that you include select('table.') on query to avoid weird issues where id from related model replaces the id of the main model. +```php +$posts = Post::with('user')->select('posts.*'); +``` +## Nested Relationships +Same strategy goes for nested relationships but do **NOTE** that ordering is not yet fully tested on nested relationships. + diff --git a/releases.md b/releases.md index abf7bde..e09cc8a 100644 --- a/releases.md +++ b/releases.md @@ -1 +1,27 @@ -# Release Notes \ No newline at end of file +# Release Notes + +- [Laravel DataTables 10.0](#10.0) + + +## Laravel DataTables 10.0 + +Laravel DataTables 10.0 splits Laravel DataTables 6.x into a main package and plugins packages for more flexibile and pluggable design. + +### Buttons Plugin +On Laravel DataTables 10.0, service classes and files are extracted into a separate package to reduce its complexity and dependencies on other packages by default. +This idea comes up from [Issue #832](https://github.com/yajra/{{package}}/issues/832) which actually makes sense since not all users are using the export functionality. + +### DomPDF +`DomPDF` dependency is now optional on Laravel DataTables 10.0 and was transferred to Buttons plugin. +And the `Buttons` plugin will now give you a choice to install it or not. +This was as a `suggest` since we now have an option to use [`snappy`](https://github.com/barryvdh/laravel-snappy) as our pdf generator. + +### Other Changes + +#### Request property +`DataTables` `request` property is now set as `protected`. To access the request instance, use the getter method `getRequest()`. + +```php +$dataTable = Datatable::of(User::query()); +$request = $dataTable->getRequest(); +``` diff --git a/remove-column.md b/remove-column.md index a5a8751..f0d2715 100644 --- a/remove-column.md +++ b/remove-column.md @@ -3,13 +3,13 @@ You can remove a column on your response by using `removeColumn` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->removeColumn('password') - ->make(true); + ->toJson(); }); ``` diff --git a/response-array.md b/response-array.md index f462000..aa73ff1 100644 --- a/response-array.md +++ b/response-array.md @@ -1,16 +1,16 @@ # Array Response -Array response is the default response of Datatables. +The default response of the package is an array of objects. If you prefer to return an array response, use `make(false)`. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->addColumn('intro', 'Hi {{$name}}!') - ->make(); + ->make(false); }); ``` @@ -28,4 +28,4 @@ Route::get('user-data', function() { [120, "Adeline Mayert-name", "rice.elian@abshire.com", "2016-07-31 23:25:50", "2016-07-31 23:25:50"] ] } -``` \ No newline at end of file +``` diff --git a/response-fractal-serializer.md b/response-fractal-serializer.md new file mode 100644 index 0000000..9adb198 --- /dev/null +++ b/response-fractal-serializer.md @@ -0,0 +1,16 @@ +# Fractal Transformer Serializer + +You can set the serializer to be used by DataTables using `setSerializer` api. Serializer should be used with `setTransformer` api. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->setTransformer(new App\Transformers\UserTransformer) + ->setSerializer(new App\Serializers\CustomSerializer) + ->toJson(); +}); +``` diff --git a/response-fractal.md b/response-fractal.md index 296c32c..3e67768 100644 --- a/response-fractal.md +++ b/response-fractal.md @@ -1,21 +1,76 @@ # Response using Transformer -When using tranformer, all column operations must be done via transformer. Thus `addColumn`, `editColumn` and `removeColumn` should be avoided when using fractal. +You'll need to install [laravel-datatables-fractal package](https://github.com/yajra/laravel-datatables-fractal) if you haven't already. + +When using tranformer, all response manipulations must be done via transformer. +Thus `addColumn`, `editColumn`, `removeColumn`, `setRowAttr`, `setClassAttr`, etc... should be avoided when using fractal. + +## Closure + +You can pass a closure which will receive an item of the result collection and should return an array. + +```php +use DataTables; +use App\User; + +Route::get('user-data', function() { + $model = User::query(); + + return DataTables::eloquent($model) + ->setTransformer(function($item){ + return [ + 'id' => (int) $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'created_at' => (string) $user->created_at, + 'updated_at' => (string) $user->updated_at, + ]; + }) + ->toJson(); +}); +``` + +Thus you can make use of Laravel API Resource. + +```php +use DataTables; +use App\User; +use App\Http\Resources\UserResource; + +Route::get('user-data', function() { + $model = User::query(); + + return DataTables::eloquent($model) + ->setTransformer(function($item){ + return UserResource::make($item)->resolve(); + }) + ->toJson(); +}); +``` + + +## Transformer + +You can use Transformer class. ```php -use Datatables; +use DataTables; use App\Transformers\UserTransformer; Route::get('user-data', function() { - $model = App\User::query(); + $model = App\User::query(); - return Datatables::eloquent($model) - ->setTransformer(new UserTransformer) - ->make(true); + return DataTables::eloquent($model) + ->setTransformer(new UserTransformer) + ->toJson(); }); ``` -Create your transformer. `app\Transformers\UserTransformer.php` +### Manual Way + +Create a transformer class, preferably named as below. + +`app\Transformers\UserTransformer.php` ```php namespace App\Transformers; @@ -53,4 +108,107 @@ class UserTransformer extends TransformerAbstract return $this->collection($posts, new PostTransformer); } } -``` \ No newline at end of file +``` + +### Artisan Command Way + +You can use `make:transformer` command to generate boilerplate. + +`php artisan make:transformer User` + +```php +namespace App\Transformers; + +use League\Fractal\TransformerAbstract; +use App\User; + +class UserTransformer extends TransformerAbstract +{ + /** + * @param \App\User $user + * @return array + */ + public function transform(User $user) + { + return [ + 'id' => (int) $user->id, + ]; + } +} +``` + +Or even with included class. + +`php artisan make:transformer User Post` + +```php +namespace App\Transformers; + +use League\Fractal\TransformerAbstract; +use App\User; +use App\Post; + +class UserTransformer extends TransformerAbstract +{ + protected $availableIncludes = ['post']; + + /** + * @param \App\User $user + * @return array + */ + public function transform(User $user) + { + return [ + 'id' => (int) $user->id, + ]; + } + + /** + * @param \App\User $user + * @return \League\Fractal\Resource\Collection + */ + public function includePost(User $user) + { + return $this->collection($user->post, new PostTransformer); + } +} +``` + +Then you can make final changes. + +```php +namespace App\Transformers; + +use League\Fractal\TransformerAbstract; +use App\User; +use App\Post; + +class UserTransformer extends TransformerAbstract +{ + protected $availableIncludes = ['posts']; + + /** + * @param \App\User $user + * @return array + */ + public function transform(User $user) + { + return [ + 'id' => (int) $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'created_at' => (string) $user->created_at, + 'updated_at' => (string) $user->updated_at, + ]; + } + + /** + * @param \App\User $user + * @return \League\Fractal\Resource\Collection + */ + public function includePost(User $user) + { + return $this->collection($user->posts, new PostTransformer); + } +} +``` diff --git a/response-object.md b/response-object.md index aa6d340..6c1c088 100644 --- a/response-object.md +++ b/response-object.md @@ -1,16 +1,16 @@ # Object Response -To convert the response of Datatables to an object, just pass `true` on `make` api. +To convert the response of DataTables to an object, use `toJson` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->addColumn('intro', 'Hi {{$name}}!') - ->make(true); + ->toJson(); }); ``` @@ -40,4 +40,4 @@ Route::get('user-data', function() { "superior_id": 1 }] } -``` \ No newline at end of file +``` diff --git a/response-only.md b/response-only.md new file mode 100644 index 0000000..972ee1c --- /dev/null +++ b/response-only.md @@ -0,0 +1,33 @@ +# Only Response + +Get only selected columns in response. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->only(['id','name']) + ->toJson(); +}); +``` + + +## Example Response + +```json +{ + "draw": 2, + "recordsTotal": 10, + "recordsFiltered": 2, + "data": [{ + "id": 476, + "name": "Esmeralda Kulas" + }, { + "id": 6, + "name": "Zachery Muller" + }] +} +``` diff --git a/response-resource.md b/response-resource.md new file mode 100644 index 0000000..19eeb14 --- /dev/null +++ b/response-resource.md @@ -0,0 +1,41 @@ +# Resource Response + +DataTables response using laravel model resource. + +```php +use DataTables; + +$users = App\User::paginate(10); + +$resource = App\Http\Resources\UserResource::collection($users); + +return DataTables::of($resource)->toJson(); +``` + + +## Example Response + +```json +{ + "draw": 10, + "recordsTotal": 10, + "recordsFiltered": 10, + "data": [{ + "id": 476, + "name": "Esmeralda Kulas", + "email": "abbott.cali@heaney.info", + "created_at": "2016-07-31 23:26:14", + "updated_at": "2016-07-31 23:26:14", + "deleted_at": null, + "superior_id": 0 + }, { + "id": 6, + "name": "Zachery Muller", + "email": "abdullah.koelpin@yahoo.com", + "created_at": "2016-07-31 23:25:43", + "updated_at": "2016-07-31 23:25:43", + "deleted_at": null, + "superior_id": 1 + }, ...] +} +``` diff --git a/response-with.md b/response-with.md index db1967d..f84221e 100644 --- a/response-with.md +++ b/response-with.md @@ -6,15 +6,15 @@ You can add additional server data on your response by using `with` api. ## Adding response using key and value ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->with('posts', 100) ->with('comments', 20) - ->make(true); + ->toJson(); }); ``` @@ -22,17 +22,53 @@ Route::get('user-data', function() { ## Adding response using array ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->with([ 'posts' => 100, 'comments' => 20, ]) - ->make(true); + ->toJson(); +}); +``` + + +## Adding response with closure. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->with('count', function() use ($model) { + return $model->count(); + }) + ->toJson(); +}); +``` + + +## Adding response with query callback. + +> This is for Query and Eloquent instance only, + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->withQuery('count', function($filteredQuery) { + return $filteredQuery->count(); + }) + ->toJson(); }); ``` @@ -64,4 +100,4 @@ Route::get('user-data', function() { "posts": 100, "comments": 20 } -``` \ No newline at end of file +``` diff --git a/scout-search.md b/scout-search.md new file mode 100644 index 0000000..5df30bb --- /dev/null +++ b/scout-search.md @@ -0,0 +1,56 @@ +# Scout Search + +**Note:** This documentation is applicable from version 10.11.0 and upwards, where external search engines can be integrated with Laravel Scout, replacing the built-in search functionality. + +Scout Search provides a fallback mechanism, so the built-in search will be used if any issues occur with the external search engines (e.g., server problems or indexing problems). + +Supported drivers: Meilisearch, Algolia + + + +## Setup + +To start using Scout Search, you need to install and configure Laravel Scout with your preferred driver. + +Once Laravel Scout is set up, you can enable Scout Search in your `dataTable` function like this: + +```php +return (new EloquentDataTable($query)) + // Enable scout search for eloquent model + ->enableScoutSearch(Product::class) + + // Add filters to scout search + ->scoutFilter(function (string $keyword) { + return 'region IN ["Germany", "France"]'; // Meilisearch + // or + return 'region:Germany OR region:France'; // Algolia + }) + + // Add filters to default search + ->filter(function (QueryBuilder $query, bool $scout_searched) { + if (!$scout_searched) + { + // Filter already added for scout search + $query->whereIn('region', ['Germany', 'France']); + } + + // Stock is not indexed so it has to be filtered after the initial scout search + $query->where('stock', '>', 50); + }, true); +``` + + + +## Additional JS script + +To control the visibility of sort icons on the frontend table, you'll need an additional JavaScript script. This script hides the sort icons when Scout Search is successful (indicating fixed ordering by search relevance) and shows them again when the search keyword is removed. + +If you are using the `laravel-datatables-html` package, you can easily include the script in your `html` function: + +```php +return $this->builder() + ->setTableId('products-table') + ->addScript('datatables::scout'); +``` + +Alternatively, you can manually fetch and include the JavaScript script into your own code from this file: resources/views/scout.blade.php diff --git a/search-panes-hide-columns.md b/search-panes-hide-columns.md new file mode 100644 index 0000000..9d51f67 --- /dev/null +++ b/search-panes-hide-columns.md @@ -0,0 +1,14 @@ +# Exclude Columns + +Some columns you might not want in your SearchPanes, to hide them you can add `->searchPanes(false)` in your column +definition: + +```php +protected function getColumns() : array +{ + return [ + Column::make('id') + ->searchPanes(false); + ] +} +``` \ No newline at end of file diff --git a/search-panes-options.md b/search-panes-options.md new file mode 100644 index 0000000..c65cd5b --- /dev/null +++ b/search-panes-options.md @@ -0,0 +1,33 @@ +# Further SearchPanes options + +```php +public function html() : \Yajra\DataTables\Html\Builder +{ + return $this->builder() + ->searchPanes( + SearchPane::make() + ->hideCount() // Hides the count next to the options, the amount of records with the filters + ->hideTotal() // Hides the total how many are available without the filters + ->clear(false) // Hides the clear button, used to clear the user selection + ->controls(false) // disable controls (search for filters) + ->layout('columns-2') // can be used to set the layout (amount of search panes in one row) + ->order(['user_id', 'age']) // Sets the order of the search panes, uses the name of the search pane + ->orderable(false) // If the order icons should be displayed in the interface + ->panes( // Can be used to add additional search panes which do not belong to any existing column + [ + // SearchPane::make()... + ] + ) + ->show(false) + ->initCollapsed(true) + ->collapse(false) + ->dtOpts( // Sets the options for the datatables inside the searchpanes + [ + 'paging' => true, + 'pagingType' => 'numbers' + ] + ) + + ); +} +``` diff --git a/search-panes-starter.md b/search-panes-starter.md new file mode 100644 index 0000000..394aa88 --- /dev/null +++ b/search-panes-starter.md @@ -0,0 +1,156 @@ +# Getting Started + +[SearchPanes](https://datatables.net/extensions/searchpanes/) ([example](https://datatables.net/extensions/searchpanes/examples/initialisation/simple.html)) +allow the user to quickly filter the datatable after predefined filters. + +> {note} To use datatables you need to make sure that the npm packages `datatables.net-select-bs4` and `datatables.net-searchpanes-bs4` are installed and added to your `app.js`/`app.css` files. + +## Adding SearchPanes to the frontend + +To be able to see SearchPanes you need to either add them fixed in the dom (displayed at all time) or add a button which +opens them as popup. + + +### Adding SearchPanes fixed in the dom + +SearchPanes can be added to a table via the dom string, in it, they are marked with a `P` if you for example +are using `Bfrtip` as dom you can use `PBfrtip` to display the SearchPanes at the top of the datatable, or `BfrtipP` +to display them at the very bottom. + +Setting the dom String with the `\Yajra\DataTables\Html\Builder`: + +```php +public function html() : \Yajra\DataTables\Html\Builder +{ + // Setting the dom string directly + return $this->builder() + ->searchPanes(SearchPane::make()) + ->addColumnDef([ + 'targets' => '_all', + 'searchPanes' => [ + 'show' => true, + 'vieTotal' => false, + 'viewCount' => false, + ], + ]) + ->dom('PBfrtip'); + + // Displaying specific column indexes + return $this->builder() + ->searchPanes(SearchPane::make()->columns([1, 2])) + ->addColumnDef([ + 'targets' => '_all', + 'searchPanes' => [ + 'show' => true, + 'vieTotal' => false, + 'viewCount' => false, + ], + ]) + ->dom('PBfrtip'); + + // Alternatively set the dom with parameters + return $this->builder() + ->searchPanes(SearchPane::make()) + ->addColumnDef([ + 'targets' => '_all', + 'searchPanes' => [ + 'show' => true, + 'vieTotal' => false, + 'viewCount' => false, + ], + ]) + ->parameters([ + 'dom' => 'PBfrtip' + ]); +} +``` + + +### Adding SearchPanes with a button + +To add a button which opens the SearchPanes you need to make one extending `searchPanes`: + +```php +public function html() : \Yajra\DataTables\Html\Builder +{ + // Adding via class + return $this->builder() + ->addColumnDef([ + 'targets' => '_all', + 'searchPanes' => [ + 'show' => true, + 'vieTotal' => false, + 'viewCount' => false, + ], + ]) + ->buttons([ + \Yajra\DataTables\Html\Button::make('searchPanes') + // other buttons... + ]); + + // Alternatively set the buttons with options + return $this->builder() + ->addColumnDef([ + 'targets' => '_all', + 'searchPanes' => [ + 'show' => true, + 'vieTotal' => false, + 'viewCount' => false, + ], + ]) + ->parameters([ + 'buttons' => ['searchPanes', /*other buttons...*/] + ]); +} +``` + + +## Adding SearchPanes to the backend + +The SearchPanes can be filled in the datatables declaration via the `searchPane()` method. The method takes the column +for which the SearchPane is, as well as the options of the SearchPane. It also allows you to set custom processing for +the options. + + +```php +public function dataTable($query) : Yajra\DataTables\DataTableAbstract +{ + return datatables() + ->eloquent($query) + // Adding the SearchPane + ->searchPane( + /* + * This is the column for which this SearchPane definition is for + */ + 'user_id', + + /* + * Here we define the options for our SearchPane. This should be either a collection or an array with the + * form: + * [ + * [ + * 'value' => 1, + * 'label' => 'display value', + * 'total' => 5, // optional + * 'count' => 3 // optional + * ], + * [ + * 'value' => 2, + * 'label' => 'display value 2', + * 'total' => 6, // optional + * 'count' => 5 // optional + * ], + * ] + */ + fn() => User::query()->select('id as value', 'name as label')->get(), + + /* + * This is the filter that gets executed when the user selects one or more values on the SearchPane. The + * values are always given in an array even if just one is selected + */ + function (\Illuminate\Database\Eloquent\Builder $query, array $values) { + return $query->whereIn('id', $values); + } + ); +} +``` diff --git a/set-filtered-records.md b/set-filtered-records.md new file mode 100644 index 0000000..5a45176 --- /dev/null +++ b/set-filtered-records.md @@ -0,0 +1,16 @@ +# Set Filtered Records + +In some cases, we need to manually set the filtered records count of our `DataTables` and skip its internal counting functionality. +To achieve this, we can use `setFilteredRecords($count)` api. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->setFilteredRecords(100) + ->toJson(); +}); +``` diff --git a/set-total-records.md b/set-total-records.md index 4d907c1..e093baf 100644 --- a/set-total-records.md +++ b/set-total-records.md @@ -1,16 +1,16 @@ # Set Total Records -In some cases, we need to manually set the total records of our `Datatables` and skip its internal counting functionality. +In some cases, we need to manually set the total records of our `DataTables` and skip its internal counting functionality. To achieve this, we can use `setTotalRecords($count)` api. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->setTotalRecords(100) - ->make(true); + ->toJson(); }); -``` \ No newline at end of file +``` diff --git a/skip-paging.md b/skip-paging.md index f3fdb48..078403f 100644 --- a/skip-paging.md +++ b/skip-paging.md @@ -1,17 +1,17 @@ # Skip Paging -To skip paging of `Datatables`, we can use `skipPaging` api or just set `paging: false` on our javascript. +To skip paging of `DataTables`, we can use `skipPaging` api or just set `paging: false` on our javascript. ## Using PHP ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::withTrashed()->query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->skipPaging() - ->make(true); + ->toJson(); }); ``` @@ -27,4 +27,4 @@ $(document).ready(function() { }); }); -``` \ No newline at end of file +``` diff --git a/skip-total-records.md b/skip-total-records.md new file mode 100644 index 0000000..0400387 --- /dev/null +++ b/skip-total-records.md @@ -0,0 +1,21 @@ +# Skip Total Records + +> Note: This is deprecated on v10. Just use setTotalRecords instead. + +Skip total records aims to improve dataTables response time by skipping the total records count query and settings its value equals to the filtered total records. + + +## Example + + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->skipTotalRecords() + ->toJson(); +}); +``` diff --git a/smart-search.md b/smart-search.md new file mode 100644 index 0000000..759ffb5 --- /dev/null +++ b/smart-search.md @@ -0,0 +1,16 @@ +# Runtime Smart Search + +You can optionally enable/disable DataTables smart search feature by using `smart` api by passing `true` or `false` as the argument. +Default argument value is `true`. + +```php +use DataTables; + +Route::get('user-data', function() { + $model = App\User::query(); + + return DataTables::eloquent($model) + ->smart(false) + ->toJson(); +}); +``` diff --git a/starts-with-search.md b/starts-with-search.md new file mode 100644 index 0000000..b44c25b --- /dev/null +++ b/starts-with-search.md @@ -0,0 +1,11 @@ +# Starts With Search + +Starts with search feature allows the package to search our tables with records that starts with the given keyword. +To enable the feature, just chain `->startsWithSearch()` on your instance. + +```php +return datatables() + ->eloquent($model) + ->startsWithSearch() + ->toJson(); +``` diff --git a/upgrade.md b/upgrade.md index c96544b..ff65f53 100644 --- a/upgrade.md +++ b/upgrade.md @@ -1,16 +1,171 @@ # Upgrade Guide + +## Upgrading from v7.x to v8.x +To upgrade Laravel DataTables from version 7.x to version 8.x: + + +```bash +composer require yajra/laravel-datatables-oracle:8.* +php artisan vendor:publish --tag=datatables --force +``` + +If you are using service approach / buttons plugin: +```bash +composer require yajra/laravel-datatables-buttons:3.* +php artisan vendor:publish --tag=datatables-buttons --force +``` + +If you are using html plugin: +```bash +composer require yajra/laravel-datatables-html:3.* +php artisan vendor:publish --tag=datatables-html --force +``` + +If you are using fractal: +```bash +composer require yajra/laravel-datatables-fractal:1.* +php artisan vendor:publish --tag=datatables-fractal --force +``` + + +## [v8] Namespace +The package namespace was updated from `Yajra\Datatables` to `Yajra\DataTables`. +> Use sublime's find and replace all feature to update all affected files. + + +## [v8] Facade +DataTables Facade was renamed to `Yajra\DataTables\Facades\DataTables`. If you want to continue using your old facade, just register the alias on your `config/app.php` file. + +```php +'Datatables' => Yajra\DataTables\Facades\DataTables::class +``` + + +## [v8] DataTables Factory class +DataTables factory class is now renamed to `DataTables` from `Datatables`. If you are injecting `Yajra\Datatables\Datatables` on your code, you must update it to `Yajra\DataTables\DataTables`. + +`DataTables::of()` method is now an alias of new `DataTables::make()` method to match Laravel's factory api structure. + + +## [v8] DataTables Buttons Changes +> See https://github.com/yajra/laravel-datatables-buttons/blob/master/CHANGELOG.md for full changelog. + +- The package namespace was updated from `Yajra\Datatables` to `Yajra\DataTables`. +> Use sublime's find and replace all feature to update all affected files. +- Constructor dependencies were removed. +- You need to instanstiate the DataTable class within the `dataTable()` method: +- The `dataTable()` method should `public` now instead of `protected`. + ```php + // FROM + public function dataTable() { + return $this->datatables->eloquent($this->query()); + } + ``` + ```php + // TO + use Yajra\DataTables\EloquentDataTable; + public function dataTable($query) { + return new EloquentDataTable($query); + } + ``` + + Or inject the factory using method injection. Note that you need to inject your classes first before the query results. + ```php + use Yajra\DataTables\DataTables; + public function dataTable(DataTables $dataTables, $query) { + return $dataTables->eloquent($query); + } + ``` +- Query method results are automatically injected on `dataTable($query)` api. + ```php + use Yajra\DataTables\DataTables; + public function dataTable($query, DataTables $dataTables) { + return $dataTables->eloquent($query); + } + + public function query() { + return Model::query(); + } + ``` +- The following methods now supports method injection: + + Action Buttons: `csv(), pdf(), excel(), printPreview()` + + Builder Methods: `ajax(), dataTable(), query()` + +- `DataTableContract` contract removed. +- `DataTableScopeContract` contract renamed to `DataTableScope`. +- `DataTableButtonsContract` contract renamed to `DataTableButtons`. + + + +## [v8] DataTables Html Changes +The package namespace was updated from `Yajra\Datatables` to `Yajra\DataTables`. +> Use sublime's find and replace all feature to update all affected files. + + +## [v8] DataTables Trashed +DataTables now supports `SoftDeletes` hence, there is no need to use `withTrashed` and `onlyTrashed`. + + + +## [v8] Functionalities Removed +- Removed `filterColumn` api magic query method in favor of closure. +- Removed support on older `snake_case` methods. +- Removed silly implementation of proxying query builder calls via magic method. +- Removed unused methods. +- Removed `withTrashed` and `onlyTrashed` api. + ## Upgrading from v6.x to v7.x - - composer require yajra/laravel-datatables-oracle - - composer require yajra/laravel-datatables-buttons - - php artisan vendor:publish --tag=datatables --force - - php artisan vendor:publish --tag=datatables-buttons --force +To upgrade Laravel Datatables from version 6.x to version 7.x: + +```sh +composer require yajra/laravel-datatables-oracle:^7.0 +php artisan vendor:publish --tag=datatables --force +``` + +### Service Approach +Service class is now extracted to own plugin, `Buttons Plugin`. If you are using the service approach, you need to perform the following: + +```sh +composer require yajra/laravel-datatables-buttons:^1.0 +``` + +Register `Yajra\Datatables\ButtonsServiceProvider::class` on `config/app.php` and publish config. + + +```php +php artisan vendor:publish --tag=datatables-buttons --force +``` + + +### Html Builder +HTML builder is now extracted to own plugin, If you are using Datatables html builder, you need to perform the following: +> HTML Builder plugin is a prerequisite of Buttons plugin. You can optionally skip this part if already installed the Buttons plugin. + +```sh +composer require yajra/laravel-datatables-html:^1.0 +php artisan vendor:publish --tag=datatables-html --force +``` + + +### XSS Protection +All columns are now escaped by default to protect us from XSS attack. To allow columns to have an html content, use `rawColumns` api. + +```php +Datatables::of(User::query()) + ->addColumn('href', 'Html Content') + ->rawColumns(['href']) + ->toJson(); +``` + ## Upgrading from v5.x to v6.x - - Change all occurrences of `yajra\Datatables` to `Yajra\Datatables`. (Use Sublime's find and replace all for faster update). - - Remove `Datatables` facade registration. - - Temporarily comment out `Yajra\Datatables\DatatablesServiceProvider`. - - Update package version on your composer.json and use `yajra/laravel-datatables-oracle: ~6.0` - - Uncomment the provider `Yajra\Datatables\DatatablesServiceProvider`. +- Change all occurrences of `yajra\Datatables` to `Yajra\Datatables`. (Use Sublime's find and replace all for faster update). +- Remove `Datatables` facade registration. +- Temporarily comment out `Yajra\Datatables\DatatablesServiceProvider`. +- Update package version on your composer.json and use `yajra/laravel-datatables-oracle: ~6.0` +- Uncomment the provider `Yajra\Datatables\DatatablesServiceProvider`. diff --git a/whitelist.md b/whitelist.md index 39578df..fe5ce12 100644 --- a/whitelist.md +++ b/whitelist.md @@ -3,13 +3,13 @@ Sorting and searching will only work on columns explicitly defined as whitelist. ```php -use Datatables; +use DataTables; Route::get('user-data', function() { $model = App\User::query(); - return Datatables::eloquent($model) + return DataTables::eloquent($model) ->whitelist(['name', 'email']) - ->make(true); + ->toJson(); }); -``` \ No newline at end of file +``` diff --git a/with-trashed.md b/with-trashed.md deleted file mode 100644 index f3efb1a..0000000 --- a/with-trashed.md +++ /dev/null @@ -1,16 +0,0 @@ -# Eloquent Model With Trashed - -When our `Model` uses `SoftDeletes` trait of Laravel, we need to implicitly tell `Datatables` to include trashed records in the results. -To achieve this, we can use `withTrashed` api. - -```php -use Datatables; - -Route::get('user-data', function() { - $model = App\User::withTrashed()->query(); - - return Datatables::eloquent($model) - ->withTrashed() - ->make(true); -}); -``` \ No newline at end of file diff --git a/xss.md b/xss.md index ab5b8a7..a8e125f 100644 --- a/xss.md +++ b/xss.md @@ -1,29 +1,51 @@ # XSS filtering -To prevent XSS attack on some of your columns, you can use `escapeColumns` api. +Since v7.0, all dataTable response are encoded to prevent XSS attack. In case you need to display html on your columns, you can use `rawColumns` api. + +> `action` column is allowed as raw by default. + + + +## Raw Columns +```php +return DataTables::eloquent(Role::select()) + ->rawColumns(['name', 'action']) + ->toJson(); +``` + +# Other XSS methods ## Escape selected fields ```php -return Datatables::eloquent(Role::select()) +return DataTables::eloquent(Role::select()) ->escapeColumns(['name']) - ->make(true); + ->toJson(); ``` ## Escape all columns ```php -return Datatables::eloquent(Role::select()) +return DataTables::eloquent(Role::select()) ->escapeColumns() - ->make(true); + ->toJson(); +``` + + +## Remove escaping of all columns + +```php +return DataTables::eloquent(Role::select()) + ->escapeColumns([]) + ->toJson(); ``` ## Escape by output index ```php -return Datatables::eloquent(Role::select()) +return DataTables::eloquent(Role::select()) ->escapeColumns([0]) ->make(); - ``` \ No newline at end of file + ```