├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json └── src ├── DataTable.php ├── DataTableAction.php ├── DataTableColumn.php ├── LinkColumn.php └── assets ├── DataTableAsset.php ├── DataTableBaseAsset.php ├── DataTableBootstrapAsset.php ├── DataTableDefaultAsset.php ├── DataTableFaAsset.php └── DataTableJuiAsset.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## v1.1.3 6 | ### Added 7 | - `DataTableAction` `query` parameter can be `Closure` 8 | 9 | ## v1.1.2 10 | ### Added 11 | - Support for bootstrap 4/5 (autodetect required bootstrap version) 12 | - Add `dataProvider` property to `DataTable` 13 | - if set, property `data` is autofilled with models from dataProvider 14 | - if models are found either in `dataProvider` or in `data`, column labels are loaded from 15 | `Model::attributes()` 16 | - restore support for custom column definitions ([#52]) 17 | 18 | ## v1.1.1 19 | ### Added 20 | - Add `extraColumns` property to `DataTable`, `DataTableColumn`, `DataTableAction` 21 | 22 | ## v1.1.0 23 | ### Added 24 | - Add `sClass` property for `DataTableColumn` class 25 | - Add `title` property for `LinkColumn` class 26 | ### Changed 27 | - Improve README 28 | - Change `options` property to `linkOptions` at LinkColumn class 29 | - Move asset classes to separate directory 30 | - Update minimal php version to 5.5.0 31 | - Reverse order CHANGELOG 32 | 33 | ## v1.0.4 34 | ### Added 35 | - php 7.2 compatibility 36 | 37 | ## v1.0.3 38 | ### Added 39 | - Data and response formatting in DataTableAction 40 | 41 | ## v1.0.2 42 | ### Fixed 43 | - Server-side pagination 44 | 45 | ## v1.0.1 46 | ### Changed 47 | - Improve README 48 | 49 | ## v1.0.0 50 | ### Changed 51 | - Move DataTable options to protected array. Add __set and __get methods. 52 | 53 | [#52]: https://github.com/NullRefExcep/yii2-datatables/issues/52 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Null Reference Exception 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Yii2 DataTables 2 | =============== 3 | 4 | Yii2 Widget for [DataTables](https://github.com/DataTables/DataTables) plug-in for jQuery 5 | 6 | ## Installation 7 | 8 | The preferred way to install this extension is through composer. 9 | 10 | Either run 11 | 12 | ``` 13 | composer require nullref/yii2-datatables 14 | ``` 15 | or add 16 | ``` 17 | "nullref/yii2-datatables": "~1.0" 18 | ``` 19 | to the require section of your `composer.json` file. 20 | 21 | ## Basic Usage 22 | 23 | ```php 24 | $dataProvider, 26 | 'columns' => [ 27 | 'id', 28 | 'name', 29 | 'email' 30 | ], 31 | ]) ?> 32 | ``` 33 | 34 | For backwards compatibility the old usage via `data` is still supported 35 | ```php 36 | $dataProvider->getModels(), 38 | 'columns' => [ 39 | 'id', 40 | 'name', 41 | 'email' 42 | ], 43 | ]) ?> 44 | ``` 45 | 46 | 47 | 48 | ## DataTable options 49 | Also you can use all [Datatables options](https://datatables.net/reference/option/) 50 | 51 | To pass them as widget options: 52 | ```php 53 | $dataProvider->getModels(), 55 | 'scrollY' => '200px', 56 | 'scrollCollapse' => true, 57 | 'paging' => false, 58 | 'columns' => [ 59 | 'name', 60 | 'email' 61 | ], 62 | 'withColumnFilter' => true, 63 | ]) ?> 64 | ``` 65 | 66 | ## Specifies header label and css class for cell 67 | 68 | ```php 69 | [ 71 | //other columns 72 | [ 73 | 'data' => 'active', 74 | 'title' => 'Is active', 75 | 'sClass' => 'active-cell-css-class', 76 | ], 77 | ], 78 | ]) ?> 79 | ``` 80 | 81 | ## Specifies datatable id 82 | 83 | ```php 84 | $dataProvider->getModels(), 86 | 'id' => 'your-datatable-id' 87 | ]) ?> 88 | ``` 89 | 90 | ## Add Links to row 91 | 92 | ```php 93 | [ 95 | //other columns 96 | [ 97 | 'class' => 'nullref\datatable\LinkColumn', 98 | 'url' => ['/model/delete'], 99 | 'linkOptions' => ['data-confirm' => 'Are you sure you want to delete this item?', 'data-method' => 'post'], 100 | 'label' => 'Delete', 101 | ], 102 | ], 103 | ]) ?> 104 | ``` 105 | 106 | Properties of `LinkColumn`: 107 | 108 | - `label` - text placed in `a` tag; 109 | - `title` - header title of column; 110 | - `url` - will be passed to `Url::to()`; 111 | - `linkOptions` - HTML options of the `a` tag; 112 | - `queryParams` - array of params added to `url`, `['id']` by default; 113 | - `render` - custom render js function. E.g: 114 | ```php 115 | //config ... 116 | 'columns' => [ 117 | //... 118 | [ 119 | 'class' => 'nullref\datatable\LinkColumn', 120 | 'queryParams' => ['some_id'], 121 | 'render' => new JsExpression('function render(data, type, row, meta ){ 122 | return "View" 123 | }'), 124 | ], 125 | ], 126 | //... 127 | ``` 128 | 129 | You should pass fields that are using at render function to `queryParams` property 130 | 131 | ## Column filtering 132 | 133 | You can add column filtering functionality by setting option `withColumnFilter` to `true` : 134 | 135 | - By default it generates a text field as filter input. 136 | - It can be replaced by a combo box using `filter` parameter when defining column. It should be a associative array 137 | where key is used as filter (value sent to server) and value for cell rendering 138 | - It can be avoided by setting `filter` to false 139 | 140 | ```php 141 | [ 143 | 'id', 144 | //... 145 | [ 146 | 'data' => 'active', 147 | 'title' => \Yii::t('app', 'Is active'), 148 | 'filter' => ['true' => 'Yes', 'false' => 'No'], 149 | ], 150 | [ 151 | 'data' => 'last_connection', 152 | 'filter' => false, 153 | ], 154 | ], 155 | ]) ?> 156 | //... 157 | ``` 158 | 159 | In this example above, filter for `active` field sent to server will contains `'true'` or `'false'` but the cell content 160 | will be `'Yes'` or `'No'` and the filter will be rendered as a combo box. 161 | 162 | No filter will be generated for `last_connection` attrribute. 163 | 164 | ## Advanced column definition 165 | 166 | Cell rendering or filter can be customized using `\nullref\datatable\DataTableColumn` class. 167 | 168 | ```php 169 | [ 171 | //other columns 172 | [ 173 | 'class' => 'nullref\datatable\DataTableColumn', // can be omitted 174 | 'data' => 'active', 175 | 'renderFiler' => new \yii\web\JsExpression('function() { ' . 176 | 'return jQuery(\' Active only\'); ' . 177 | '}'), 178 | 'render' => new \yii\web\JsExpression('function(data, type, row, meta) { ' . 179 | 'return jQuery(\'\')' . 180 | ' .prop(\'checked\', data == \'true\'); ' . 181 | '}'), 182 | ], 183 | ], 184 | ]) ?> 185 | ``` 186 | 187 | ## Styling 188 | 189 | `DataTables` supports several styling solutions, including `Bootstrap`, `jQuery UI`, `Foundation`. 190 | 191 | ```php 192 | 'assetManager' => [ 193 | 'bundles' => [ 194 | 'nullref\datatable\assets\DataTableAsset' => [ 195 | 'styling' => \nullref\datatable\assets\DataTableAsset::STYLING_BOOTSTRAP, 196 | ] 197 | ], 198 | ], 199 | ``` 200 | 201 | ### Bootstrap 202 | 203 | Bootstrap tables require the class 'table', so you'll need to add the 'table' class using `tableOptions` via the widget config. 204 | 205 | ```php 206 | $dataProvider->getModels(), 208 | 'tableOptions' => [ 209 | 'class' => 'table', 210 | ], 211 | 'columns' => [ 212 | 'id', 213 | 'name', 214 | 'email', 215 | ], 216 | ]) ?> 217 | ``` 218 | 219 | ## Custom assets 220 | It's possible to use custom styles and scripts: 221 | ```php 222 | 'nullref\datatable\assets\DataTableAsset' => [ 223 | 'sourcePath' => '@webroot/js/plugin/datatables/', 224 | 'js' => [ 225 | 'jquery.dataTables-1.10-cust.js', 226 | 'DT_bootstrap.js', 227 | ], 228 | 'css' => [ 229 | 'data-table.css', 230 | ], 231 | 'styling' => false, 232 | ] 233 | ``` 234 | 235 | ## Server-side processing 236 | 237 | To enable server-side processing add `DataTableAction` to controller like this: 238 | 239 | ```php 240 | class SomeController extends Controller 241 | { 242 | public function actions() 243 | { 244 | return [ 245 | 'datatables' => [ 246 | 'class' => 'nullref\datatable\DataTableAction', 247 | 'query' => Model::find(), 248 | ], 249 | ]; 250 | } 251 | } 252 | ``` 253 | 254 | Searching and ordering can be customized using closures 255 | ```php 256 | public function actions() 257 | { 258 | return [ 259 | 'datatables' => [ 260 | 'class' => 'nullref\datatable\DataTableAction', 261 | 'query' => Model::find(), 262 | 'applyOrder' => function($query, $columns, $order) { 263 | //custom ordering logic 264 | $orderBy = []; 265 | foreach ($order as $orderItem) { 266 | $orderBy[$columns[$orderItem['column']]['data']] = $orderItem['dir'] == 'asc' ? SORT_ASC : SORT_DESC; 267 | } 268 | return $query->orderBy($orderBy); 269 | }, 270 | 'applyFilter' => function($query, $columns, $search) { 271 | //custom search logic 272 | $modelClass = $query->modelClass; 273 | $schema = $modelClass::getTableSchema()->columns; 274 | foreach ($columns as $column) { 275 | if ($column['searchable'] == 'true' && array_key_exists($column['data'], $schema) !== false) { 276 | $value = empty($search['value']) ? $column['search']['value'] : $search['value']; 277 | $query->orFilterWhere(['like', $column['data'], $value]); 278 | } 279 | } 280 | return $query; 281 | }, 282 | ], 283 | ]; 284 | } 285 | ``` 286 | 287 | If you need to get some relation data you can call `join` or similar methods from `$query` in `applyFilter` closure. 288 | 289 | You may also specify a closure for `query` in `DataTableAction` config if you need complex query like in the following code: 290 | ```php 291 | /** ... */ 292 | 'query' => function() { 293 | $calculatedValue = calculate_value_for_query(); 294 | 295 | return Model::find()->where(['calculated_value' => $calculatedValue]); 296 | }, 297 | /** ... */ 298 | ``` 299 | 300 | And add options to widget: 301 | 302 | ```php 303 | true, 306 | 'ajax' => '/site/datatables', 307 | ]) ?> 308 | ``` 309 | 310 | 311 | ## Extra columns 312 | 313 | If need to use some custom fields from your model at your render function at column you could pass `extraColumns` param. 314 | 315 | It available at DataTable widget, column and server side action definition: 316 | 317 | ```php 318 | $dataProvider->getModels(), 321 | 'extraColumns' => ['customPrice'], 322 | 'columns' => [ 323 | [ 324 | 'title' => 'Custom column', 325 | 'extraColumns' => ['customField'], 326 | 'render' => new JsExpression($customColumnRender), 327 | ], 328 | ], 329 | ]) ?> 330 | ``` 331 | 332 | ```php 333 | class SomeController extends Controller 334 | { 335 | public function actions() 336 | { 337 | return [ 338 | 'datatables' => [ 339 | 'class' => 'nullref\datatable\DataTableAction', 340 | 'query' => Model::find(), 341 | 'extraColumns' => ['customPrice'], 342 | ], 343 | ]; 344 | } 345 | } 346 | ``` 347 | 348 | ```php 349 | ['customPrice'], 352 | ]) ?> 353 | ``` 354 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nullref/yii2-datatables", 3 | "description": "Yii2 Extension for DataTables jQuery plug-in", 4 | "type": "yii2-extension", 5 | "homepage": "https://github.com/NullRefExcep/yii2-datatables", 6 | "keywords": [ 7 | "yii2", 8 | "yii", 9 | "widget", 10 | "jquery", 11 | "datatable", 12 | "datatables", 13 | "plugin", 14 | "jQuery" 15 | ], 16 | "license": "MIT", 17 | "authors": [ 18 | { 19 | "name": "Serhiy Vinichuk", 20 | "email": "serhiyvinichuk@gmail.com" 21 | }, 22 | { 23 | "name": "Dmytro Karpovych", 24 | "email": "ZAYEC77@gmail.com" 25 | }, 26 | { 27 | "name": "Radon8472", 28 | "email": "develop@radon-software.net", 29 | "homepage": "https://github.com/Radon8472", 30 | "role": "Contributor" 31 | }, 32 | { 33 | "name": "Oleksandr Lynnyk", 34 | "email": "alexandr.linnik@gmail.com", 35 | "homepage": "https://github.com/alxlnk", 36 | "role": "Contributor" 37 | } 38 | ], 39 | "minimum-stability": "stable", 40 | "require": { 41 | "php": ">=5.5.0", 42 | "yiisoft/yii2": "~2.0.13", 43 | "bower-asset/datatables": "~1.10.15", 44 | "bower-asset/datatables-plugins": "~1.10.15", 45 | "bower-asset/datatables.net-bs4": "~1.10.15", 46 | "npm-asset/datatables.net-bs5": "~1.10.15" 47 | }, 48 | "autoload": { 49 | "psr-4": { 50 | "nullref\\datatable\\": "src/" 51 | } 52 | }, 53 | "config": { 54 | "fxp-asset": { 55 | "installer-paths": { 56 | "bower-asset-library": "vendor/bower" 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/DataTable.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable; 9 | 10 | use nullref\datatable\assets\DataTableAsset; 11 | use yii\base\Model; 12 | use yii\base\Widget; 13 | use yii\data\ActiveDataProvider; 14 | use yii\data\ArrayDataProvider; 15 | use yii\db\ActiveQueryInterface; 16 | use yii\helpers\ArrayHelper; 17 | use yii\helpers\Html; 18 | use yii\helpers\Inflector; 19 | use yii\helpers\Json; 20 | 21 | /** 22 | * Class DataTable 23 | * @package nullref\datatable 24 | * Features 25 | * @property bool $autoWidth Feature control DataTables' smart column width handling 26 | * @property bool $deferRender Feature control deferred rendering for additional speed of initialisation. 27 | * @property bool $info Feature control table information display field 28 | * @property bool $jQueryUI Use markup and classes for the table to be themed by jQuery UI ThemeRoller. 29 | * @property bool $lengthChange Feature control the end user's ability to change the paging display length of the table. 30 | * @property bool $ordering Feature control ordering (sorting) abilities in DataTables. 31 | * @property bool $paging Enable or disable table pagination. 32 | * @property bool $processing Feature control the processing indicator. 33 | * @property bool $scrollX Enable horizontal scrolling 34 | * @property bool $scrollY Enable vertical scrolling 35 | * @property bool $searching Feature control search (filtering) abilities 36 | * @property bool $serverSide Enable server-side filtering, paging and sorting calculations 37 | * @property bool $stateSave Restore table state on page reload 38 | * @property array $language 39 | * Options 40 | * @property array $ajax Load data for the table's content from an Ajax source 41 | * @property array $data Data to use as the display data for the table. 42 | * @property array $columnDefs Set column definition initialisation properties. 43 | * @property array $columns Set column specific initialisation properties. 44 | * @property bool|int|array $deferLoading Delay the loading of server-side data until second draw 45 | * @propert bool $destroy Destroy any existing table matching the selector and replace with the new options. 46 | * @property int $displayStart Initial paging start point 47 | * @property string $dom Define the table control elements to appear on the page and in what order 48 | * @property array $lengthMenu Change the options in the page length `select` list. 49 | * @property bool $orderCellsTop Control which cell the order event handler will be applied to in a column 50 | * @property bool $orderClasses Highlight the columns being ordered in the table's body 51 | * @property array $order Initial order (sort) to apply to the table 52 | * @property array $orderFixed Ordering to always be applied to the table 53 | * @property bool $orderMulti Multiple column ordering ability control. 54 | * @property int $pageLength Change the initial page length (number of rows per page) 55 | * @property string $pagingType Pagination button display options. 56 | * @property string|array $renderer Display component renderer types 57 | * @property bool $retrieve Retrieve an existing DataTables instance 58 | * @property bool $scrollCollapse Allow the table to reduce in height when a limited number of rows are shown. 59 | * @property array $search 60 | * @property array $searchCols Define an initial search for individual columns. 61 | * @property array $searchDelay Set a throttle frequency for searching 62 | * @property int $stateDuration Saved state validity duration 63 | * @property array $stripeClasses Set the zebra stripe class names for the rows in the table. 64 | * @property int $tabIndex Tab index control for keyboard navigation 65 | * Callbacks 66 | * @property string $createdRow Callback for whenever a TR element is created for the table's body. 67 | * @property string $drawCallback Function that is called every time DataTables performs a draw. 68 | * @property string $footerCallback Footer display callback function. 69 | * @property string $formatNumber Number formatting callback function. 70 | * @property string $headerCallback Header display callback function. 71 | * @property string $infoCallback Table summary information display callback. 72 | * @property string $initComplete Initialisation complete callback. 73 | * @property string $preDrawCallback Pre-draw callback. 74 | * @property string $rowCallback Row draw callback. 75 | * @property string $stateLoadCallback Callback that defines where and how a saved state should be loaded. 76 | * @property string $stateLoaded State loaded callback. 77 | * @property string $stateLoadParams State loaded - data manipulation callback 78 | * @property string $stateSaveCallback Callback that defines how the table state is stored and where. 79 | * @property string $stateSaveParams State save - data manipulation callback 80 | */ 81 | class DataTable extends Widget 82 | { 83 | const COLUMN_TYPE_DATE = 'date'; 84 | const COLUMN_TYPE_NUM = 'num'; 85 | const COLUMN_TYPE_NUM_FMT = 'num-fmt'; 86 | const COLUMN_TYPE_HTML_NUM = 'html-num'; 87 | const COLUMN_TYPE_HTML_NUM_FMT = 'html-num-fmt'; 88 | const COLUMN_TYPE_STRING = 'string'; 89 | 90 | const PAGING_SIMPLE = 'simple'; 91 | const PAGING_SIMPLE_NUMBERS = 'simple_numbers'; 92 | const PAGING_FULL = 'full'; 93 | const PAGING_FULL_NUMBERS = 'full_numbers'; 94 | public $id; 95 | 96 | /** 97 | * @var array Html options for table 98 | */ 99 | public $tableOptions = []; 100 | 101 | /** 102 | * @var array 103 | */ 104 | public $extraColumns = []; 105 | 106 | public $withColumnFilter; 107 | /** @var bool */ 108 | public $globalVariable = false; 109 | protected $_options = []; 110 | 111 | /** 112 | * @var \yii\data\DataProviderInterface the data provider for the view. 113 | */ 114 | protected $_dataProvider; 115 | 116 | protected $_extraColumns = []; 117 | 118 | /** 119 | * @throws \yii\base\InvalidConfigException 120 | * @throws \Exception if ArrayHelper::getValue() 121 | */ 122 | public function init() 123 | { 124 | parent::init(); 125 | if ($this->data === null) { 126 | $this->data = is_null($this->_dataProvider) ? [] : $this->_dataProvider->getModels(); 127 | } 128 | DataTableAsset::register($this->getView()); 129 | $this->initColumns(); 130 | $this->initData(); 131 | } 132 | 133 | /** 134 | * @throws \yii\base\InvalidConfigException 135 | */ 136 | protected function initColumns() 137 | { 138 | $this->_extraColumns = $this->extraColumns; 139 | if (isset($this->_options['columns'])) { 140 | $demoObject = $this->getModel(); 141 | foreach ($this->_options['columns'] as $key => $value) { 142 | if (!is_array($value)) { 143 | $value = [ 144 | 'class' => DataTableColumn::class, 145 | 'attribute' => $value, 146 | 'label' => $demoObject instanceof \yii\base\Model 147 | ? $demoObject->getAttributeLabel($value) 148 | : Inflector::camel2words($value) 149 | ]; 150 | } 151 | if (isset($value['type'])) { 152 | if ($value['type'] == 'link') { 153 | $value['class'] = LinkColumn::className(); 154 | unset($value['type']); 155 | } 156 | } 157 | if (!isset($value['class'])) { 158 | $value['class'] = DataTableColumn::className(); 159 | } 160 | if (isset($value['class'])) { 161 | $column = \Yii::createObject($value); 162 | if ($column instanceof DataTableColumn) { 163 | $this->_extraColumns = array_merge($this->_extraColumns, $column->getExtraColumns()); 164 | } 165 | $this->_options['columns'][$key] = $column; 166 | } 167 | } 168 | } 169 | 170 | } 171 | 172 | /** 173 | * Detect a model class from `dataProvider` or `data` attributes 174 | * 175 | * @see \yii\grid\DataColumn::getHeaderCellLabel() 176 | * 177 | * return Model|null NULL is returned when only property $data is defined, and is either empty or first entry is not of type model 178 | */ 179 | protected function getModel() 180 | { 181 | $provider = $this->_dataProvider; 182 | if ($provider instanceof ActiveDataProvider && $provider->query instanceof ActiveQueryInterface) { 183 | /* @var $modelClass Model */ 184 | $modelClass = $provider->query->modelClass; 185 | $model = $modelClass::instance(); 186 | } elseif ($provider instanceof ArrayDataProvider && $provider->modelClass !== null) { 187 | /* @var $modelClass Model */ 188 | $modelClass = $provider->modelClass; 189 | $model = $modelClass::instance(); 190 | } else { 191 | $models = $this->data; 192 | //$model = (count($models)) ? $models[0] : null; 193 | $model = reset($models); 194 | } 195 | return $model instanceof Model ? $model : null; 196 | } 197 | 198 | /** 199 | * @throws \Exception if ArrayHelper::getValue() throws 200 | */ 201 | private function initData() 202 | { 203 | $this->_extraColumns = array_unique($this->_extraColumns); 204 | if (array_key_exists('data', $this->_options)) { 205 | $data = []; 206 | 207 | foreach ($this->_options['data'] as $obj) { 208 | $row = []; 209 | foreach ($this->_options['columns'] as $column) { 210 | if ($column instanceof DataTableColumn) { 211 | if ($column->data) { 212 | $value = ArrayHelper::getValue($obj, $column->data); 213 | if (($pos = strrpos($column->data, '.')) !== false) { 214 | $keys = explode('.', $column->data); 215 | $a = $value; 216 | foreach (array_reverse($keys) as $key) { 217 | $a = [$key => $a]; 218 | } 219 | $row[$keys[0]] = $a[$keys[0]]; 220 | } else { 221 | $row[$column->data] = $value; 222 | } 223 | } 224 | } 225 | } 226 | foreach ($this->_extraColumns as $column) { 227 | $row[$column] = ArrayHelper::getValue($obj, $column); 228 | } 229 | if ($row) { 230 | $data[] = $row; 231 | } 232 | } 233 | $this->_options['data'] = $data; 234 | } 235 | } 236 | 237 | public function run() 238 | { 239 | $id = isset($this->id) ? $this->id : $this->getId(); 240 | echo Html::beginTag('table', ArrayHelper::merge(['id' => $id], $this->tableOptions)); 241 | 242 | echo Html::endTag('table'); 243 | 244 | $globalVariable = $this->globalVariable ? "window[$id] =" : ''; 245 | if ($this->withColumnFilter) { 246 | $encodedParams = Json::encode($this->getParams()); 247 | 248 | $this->getView()->registerJs( 249 | <<'); 255 | jQuery('#${id} thead tr th').each(function(i) 256 | { 257 | var cell = jQuery('') 258 | .attr('colspan', jQuery(this).attr('colspan')) 259 | .attr('class', jQuery(this).attr('class')) 260 | .attr('tabindex', jQuery(this).attr('tabindex')) 261 | .attr('aria-controls', jQuery(this).attr('aria-controls')) 262 | .removeClass('sorting sorting_disabled') 263 | .appendTo(filterRow); 264 | 265 | if (params.columns && params.columns[i] && params.columns[i].renderFilter) { 266 | cell.html(jQuery.isFunction(params.columns[i].renderFilter) ? params.columns[i].renderFilter(table) : params.columns[i].renderFilter); 267 | } 268 | }); 269 | jQuery('#${id} thead').append(filterRow); 270 | jQuery('#${id} thead tr:eq(1) td').each( function (i) 271 | { 272 | jQuery(':input', this).on('keyup change', function () { 273 | if (table.column(i).search() !== jQuery(this).val()) { 274 | table 275 | .column(i) 276 | .search(jQuery(this).val()) 277 | .draw(); 278 | } 279 | } ); 280 | } ); 281 | })(); 282 | JS 283 | ); 284 | } else { 285 | $this->getView()->registerJs($globalVariable . 'jQuery("#' . $id . '").DataTable(' . Json::encode($this->getParams()) . ');'); 286 | } 287 | } 288 | 289 | protected function getParams() 290 | { 291 | return $this->_options; 292 | } 293 | 294 | public function __get($name) 295 | { 296 | if ($name == 'dataProvider') { 297 | return $this->_dataProvider; 298 | } 299 | return isset($this->_options[$name]) ? $this->_options[$name] : null; 300 | } 301 | 302 | public function __set($name, $value) 303 | { 304 | if ($name == 'dataProvider') { 305 | return $this->_dataProvider = $value; 306 | } 307 | return $this->_options[$name] = $value; 308 | } 309 | 310 | } 311 | -------------------------------------------------------------------------------- /src/DataTableAction.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable; 9 | 10 | 11 | use Closure; 12 | use Yii; 13 | use yii\base\Action; 14 | use yii\base\InvalidConfigException; 15 | use yii\data\ActiveDataProvider; 16 | use yii\db\ActiveQuery; 17 | use yii\db\ActiveRecord; 18 | use yii\helpers\ArrayHelper; 19 | use yii\web\Response; 20 | 21 | /** 22 | * Action for processing ajax requests from DataTables. 23 | * @see http://datatables.net/manual/server-side for more info 24 | * @package nullref\datatable 25 | */ 26 | class DataTableAction extends Action 27 | { 28 | /** 29 | * Types of request method 30 | */ 31 | const REQUEST_METHOD_GET = 'GET'; 32 | const REQUEST_METHOD_POST = 'POST'; 33 | 34 | /** 35 | * @see \nullref\datatable\DataTableAction::getParam 36 | * @var string 37 | */ 38 | public $requestMethod = self::REQUEST_METHOD_GET; 39 | 40 | /** 41 | * @var ActiveQuery|Closure 42 | */ 43 | public $query; 44 | 45 | /** 46 | * Applies ordering according to params from DataTable 47 | * Signature is following: 48 | * function ($query, $columns, $order) 49 | * @var callable 50 | */ 51 | public $applyOrder; 52 | 53 | /** 54 | * Applies filtering according to params from DataTable 55 | * Signature is following: 56 | * function ($query, $columns, $search) 57 | * @var callable 58 | */ 59 | public $applyFilter; 60 | 61 | /** 62 | * Format data 63 | * Signature is following: 64 | * function ($query, $columns) 65 | * @var callable 66 | */ 67 | public $formatData; 68 | 69 | /** 70 | * Format response 71 | * Signature is following: 72 | * function ($response) 73 | * @var callable 74 | */ 75 | public $formatResponse; 76 | 77 | /** 78 | * Add extra fields to dataset 79 | * These fields could be used at render function 80 | * 81 | * @var array 82 | */ 83 | public $extraColumns = []; 84 | 85 | /** 86 | * Check if query is configured 87 | * @throws InvalidConfigException 88 | */ 89 | public function init() 90 | { 91 | if ($this->query === null) { 92 | throw new InvalidConfigException(get_class($this) . '::$query must be set.'); 93 | } 94 | 95 | if ($this->query instanceof Closure) { 96 | $this->query = call_user_func($this->query); 97 | } 98 | 99 | if ($this->formatData === null) { 100 | $this->formatData = function ($query, $columns) { 101 | $rows = []; 102 | foreach ($query->all() as $obj) { 103 | $row = []; 104 | foreach ($columns as $column) { 105 | if ($column['data']) { 106 | $value = ArrayHelper::getValue($obj, $column['data'], null); 107 | if (($pos = strrpos($column['data'], '.')) !== false) { 108 | $keys = explode('.', $column['data']); 109 | $a = $value; 110 | foreach (array_reverse($keys) as $key) { 111 | $a = [$key => $a]; 112 | } 113 | $row[$keys[0]] = $a[$keys[0]]; 114 | } else { 115 | $row[$column['data']] = $value; 116 | } 117 | } 118 | } 119 | $rows[] = $row; 120 | } 121 | 122 | return $rows; 123 | }; 124 | } 125 | } 126 | 127 | /** 128 | * @return array|ActiveRecord[] 129 | */ 130 | public function run() 131 | { 132 | /** @var ActiveQuery $originalQuery */ 133 | $originalQuery = $this->query; 134 | $filterQuery = clone $originalQuery; 135 | $draw = $this->getParam('draw'); 136 | $filterQuery->where = null; 137 | $search = $this->getParam('search', ['value' => null, 'regex' => false]); 138 | $columns = $this->getParam('columns', []); 139 | $order = $this->getParam('order', []); 140 | $filterQuery = $this->applyFilter($filterQuery, $columns, $search); 141 | $filterQuery = $this->applyOrder($filterQuery, $columns, $order); 142 | if (!empty($originalQuery->where)) { 143 | $filterQuery->andWhere($originalQuery->where); 144 | } 145 | $filterQuery 146 | ->offset($this->getParam('start', 0)) 147 | ->limit($this->getParam('length', -1)); 148 | $dataProvider = new ActiveDataProvider(['query' => $filterQuery, 'pagination' => ['pageSize' => Yii::$app->request->getQueryParam('length', 10)]]); 149 | Yii::$app->response->format = Response::FORMAT_JSON; 150 | try { 151 | $allColumns = array_merge($columns, $this->getExtraColumns()); 152 | $response = [ 153 | 'draw' => (int)$draw, 154 | 'recordsTotal' => (int)$originalQuery->count(), 155 | 'recordsFiltered' => (int)$dataProvider->getTotalCount(), 156 | 'data' => $this->formatData($filterQuery, $allColumns), 157 | ]; 158 | } catch (\Exception $e) { 159 | return ['error' => $e->getMessage()]; 160 | } 161 | 162 | return $this->formatResponse($response); 163 | } 164 | 165 | /** 166 | * Extract param from request 167 | * @param $name 168 | * @param null $defaultValue 169 | * @return mixed 170 | */ 171 | protected function getParam($name, $defaultValue = null) 172 | { 173 | return $this->requestMethod == self::REQUEST_METHOD_GET ? 174 | Yii::$app->request->getQueryParam($name, $defaultValue) : 175 | Yii::$app->request->getBodyParam($name, $defaultValue); 176 | } 177 | 178 | /** 179 | * @param ActiveQuery $query 180 | * @param array $columns 181 | * @param array $search 182 | * @return ActiveQuery 183 | * @throws InvalidConfigException 184 | */ 185 | public function applyFilter(ActiveQuery $query, $columns, $search) 186 | { 187 | if ($this->applyFilter !== null) { 188 | return call_user_func($this->applyFilter, $query, $columns, $search); 189 | } 190 | 191 | /** @var \yii\db\ActiveRecord $modelClass */ 192 | $modelClass = $query->modelClass; 193 | $schema = $modelClass::getTableSchema()->columns; 194 | foreach ($columns as $column) { 195 | if ($column['searchable'] == 'true' && array_key_exists($column['data'], $schema) !== false) { 196 | $value = empty($search['value']) ? $column['search']['value'] : $search['value']; 197 | $query->orFilterWhere(['like', $column['data'], $value]); 198 | } 199 | } 200 | return $query; 201 | } 202 | 203 | /** 204 | * @param ActiveQuery $query 205 | * @param array $columns 206 | * @param array $order 207 | * @return ActiveQuery 208 | */ 209 | public function applyOrder(ActiveQuery $query, $columns, $order) 210 | { 211 | if ($this->applyOrder !== null) { 212 | return call_user_func($this->applyOrder, $query, $columns, $order); 213 | } 214 | 215 | foreach ($order as $key => $item) { 216 | if (array_key_exists('orderable', $columns[$item['column']]) && $columns[$item['column']]['orderable'] === 'false') { 217 | continue; 218 | } 219 | $sort = $item['dir'] == 'desc' ? SORT_DESC : SORT_ASC; 220 | $query->addOrderBy([$columns[$item['column']]['data'] => $sort]); 221 | } 222 | return $query; 223 | } 224 | 225 | /** 226 | * Prepare extraColumns for 227 | */ 228 | protected function getExtraColumns() 229 | { 230 | return array_map(function ($column) { 231 | return ['data' => $column]; 232 | }, $this->extraColumns); 233 | } 234 | 235 | /** 236 | * @param ActiveQuery $query 237 | * @param array $columns 238 | * @return array|ActiveRecord[] 239 | */ 240 | public function formatData(ActiveQuery $query, $columns) 241 | { 242 | return call_user_func($this->formatData, $query, $columns); 243 | } 244 | 245 | /** 246 | * @param array $response 247 | * @return array|ActiveRecord[] 248 | */ 249 | public function formatResponse($response) 250 | { 251 | if ($this->formatResponse !== null) { 252 | return call_user_func($this->formatResponse, $response); 253 | } 254 | 255 | return $response; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/DataTableColumn.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable; 9 | 10 | use yii\base\Arrayable; 11 | use yii\base\InvalidConfigException; 12 | use yii\base\Widget; 13 | use yii\helpers\Html; 14 | use yii\helpers\Inflector; 15 | use yii\web\JsExpression; 16 | 17 | /** 18 | * Class DataTableColumn 19 | * 20 | * @package nullref\datatable 21 | * 22 | * Features 23 | * 24 | * @property string $type possible values (num, num-fmt, html-num, html-num-fmt, html, string) 25 | * @property bool $orderable Using this parameter, you can remove the end user's ability to order upon a column. 26 | * @property bool $searchable Using this parameter, you can define if DataTables should include this column in the filterable data in the table 27 | * @property bool $visible show and hide columns dynamically through use of this option 28 | * @property string $width This parameter can be used to define the width of a column, and may take any CSS value (3em, 20px etc). 29 | * @property string $cellType Change the cell type created for the column - either TD cells or TH cells 30 | * @property string $contentPadding Add padding to the text content used when calculating the optimal width for a table. 31 | * @property string $orderDataType 32 | * 33 | * Check the full list of supported properties 34 | * 35 | * @see: https://datatables.net/reference/option/columns 36 | */ 37 | class DataTableColumn extends Widget implements Arrayable 38 | { 39 | /** 40 | * @var string the attribute name associated with this column. 41 | */ 42 | public $data; 43 | 44 | /** 45 | * @var string label to be displayed in the header. 46 | * If it is not set [[\yii\helpers\Inflector::camel2words()]] will be used to get a label. 47 | */ 48 | public $title; 49 | 50 | /** 51 | * @var array the HTML attributes for the filter input fields. This property is used in combination with 52 | * the [[filter]] property. When [[filter]] is not set or is an array, this property will be used to 53 | * render the HTML attributes for the generated filter input fields. 54 | * 55 | * Empty `id` in the default value ensures that id would not be obtained from the model attribute thus 56 | * providing better performance. 57 | * 58 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. 59 | */ 60 | public $filterInputOptions = ['class' => 'form-control', 'id' => null]; 61 | 62 | /** @var JsExpression Javascript (function or expression) used to display the filter */ 63 | public $renderFilter; 64 | 65 | /** @var JsExpression Javascript (function) used to display the value. */ 66 | public $render; 67 | 68 | /** @var string CSS class for column cell */ 69 | public $sClass = ''; 70 | 71 | public $className = ''; 72 | 73 | /** 74 | * Add extra fields to dataset 75 | * These fields could be used at render function 76 | * 77 | * @var array 78 | */ 79 | public $extraColumns = []; 80 | 81 | /** 82 | * @var array|null|false Indicating if a filter will be displayed or not. 83 | * 84 | * - If this property is not set, a text field will be generated as the filter input with attributes defined 85 | * with [[filterInputOptions]]. 86 | * - If this property is an array, a dropdown list will be generated that uses this property value as 87 | * the list options. 88 | * - If you don't want a filter for this data column, set this value to be false. 89 | */ 90 | protected $filter; 91 | 92 | private $_options = []; 93 | 94 | /** 95 | * Check if all required properties is set 96 | */ 97 | public function init() 98 | { 99 | parent::init(); 100 | 101 | if ($this->data === null && $this->render === null) { 102 | throw new InvalidConfigException("Either 'data' or 'render' properties must be specified."); 103 | } 104 | 105 | if ($this->title === null && !is_null($this->attribute)) { 106 | $this->title = Inflector::camel2words($this->attribute); 107 | } 108 | 109 | if ($this->render === null) { 110 | $this->render = $this->getJsRender(); 111 | } 112 | 113 | if ($this->renderFilter === null) { 114 | $this->renderFilter = $this->getJsFilter(); 115 | } 116 | } 117 | 118 | /** 119 | * @return JsExpression 120 | */ 121 | public function getJsRender() 122 | { 123 | if (is_array($this->filter)) { 124 | $select = "switch (data) {"; 125 | 126 | foreach ($this->filter as $key => $value) { 127 | $key = Html::encode($key); 128 | $value = Html::encode($value); 129 | $select .= "\n\tcase '{$key}': return '{$value}';"; 130 | } 131 | $select .= "\n\tdefault: return data;"; 132 | $select .= "\n}"; 133 | 134 | return new JsExpression("function render(data, type, row, meta) { {$select} }"); 135 | } else { 136 | return new JsExpression("function render(data, type, row, meta){ return data; }"); 137 | } 138 | } 139 | 140 | /** 141 | * @return JsExpression 142 | */ 143 | public function getJsFilter() 144 | { 145 | $jsTitle = Html::encode($this->label); 146 | $jsClass = Html::encode($this->filterInputOptions['class']); 147 | $jsId = $this->filterInputOptions['id'] ? Html::encode($this->filterInputOptions['id']) : $this->getId(); 148 | if (is_array($this->filter)) { 149 | $select = "jQuery('')\n" . 150 | "\t.addClass('{$jsClass}')\n" . 151 | "\t.width('100%')\n" . 152 | "\t.attr('id', '{$jsId}')\n" . 153 | "\t.append(jQuery(''))"; 154 | 155 | foreach ($this->filter as $key => $value) { 156 | $key = Html::encode($key); 157 | $value = Html::encode($value); 158 | $select .= "\n\t.append(jQuery('', {\n\t\t" 159 | . "'value': serverSide ? '{$key}' : '{$value}',\n\t\t" 160 | . "'text': '{$value}'\n\t" 161 | . "}))"; 162 | } 163 | 164 | return new JsExpression("function(table) { var serverSide = table.page.info().serverSide; return {$select}; }"); 165 | } else if ($this->filter !== false) { 166 | return new JsExpression( 167 | "function() {" . 168 | "return jQuery('')\n" . 169 | "\t.addClass('{$jsClass}')\n" . 170 | "\t.width('100%')\n" . 171 | "\t.attr('id', '{$jsId}');\n" . 172 | "}" 173 | ); 174 | } else { 175 | return new JsExpression('jQuery()'); 176 | } 177 | } 178 | 179 | public function setAttribute($attribute) 180 | { 181 | $this->data = $attribute; 182 | } 183 | 184 | public function getAttribute() 185 | { 186 | return $this->data; 187 | } 188 | 189 | public function setLabel($label) 190 | { 191 | $this->title = $label; 192 | } 193 | 194 | public function getLabel() 195 | { 196 | return $this->title; 197 | } 198 | 199 | /** 200 | * @return array|false|null 201 | */ 202 | public function getFilter() 203 | { 204 | return $this->filter; 205 | } 206 | 207 | /** 208 | * @param array|false|null $filter 209 | */ 210 | public function setFilter($filter) 211 | { 212 | $this->filter = $filter; 213 | } 214 | 215 | /** 216 | * @return array 217 | */ 218 | public function getExtraColumns() 219 | { 220 | return $this->extraColumns; 221 | } 222 | 223 | public function __get($name) 224 | { 225 | return $this->canGetProperty($name, true) 226 | ? parent::__get($name) 227 | : (isset($this->_options[$name]) ? $this->_options[$name] : null); 228 | } 229 | 230 | public function __set($name, $value) 231 | { 232 | if ($this->canSetProperty($name, true)) 233 | return parent::__set($name, $value); 234 | else 235 | return $this->_options[$name] = $value; 236 | } 237 | 238 | /** 239 | * @inheritDoc 240 | */ 241 | public function fields() 242 | { 243 | return \Yii::getObjectVars($this); 244 | } 245 | 246 | /** 247 | * @inheritDoc 248 | */ 249 | public function extraFields() 250 | { 251 | return $this->_options; 252 | } 253 | 254 | /** 255 | * @inheritDoc 256 | */ 257 | public function toArray(array $fields = [], array $expand = [], $recursive = true) 258 | { 259 | return $recursive 260 | ? array_merge_recursive($this->fields(), $this->extraFields()) 261 | : array_merge($this->fields(), $this->extraFields()); 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /src/LinkColumn.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable; 9 | 10 | use yii\helpers\Html; 11 | use yii\helpers\Json; 12 | use yii\web\JsExpression; 13 | 14 | class LinkColumn extends DataTableColumn 15 | { 16 | public $queryParams = ['id']; 17 | public $url; 18 | public $label; 19 | public $linkOptions = []; 20 | public $searchable = false; 21 | public $orderable = false; 22 | 23 | protected $filter = false; 24 | 25 | public function init() 26 | { 27 | if (empty($this->linkOptions['id'])) { 28 | $this->linkOptions['id'] = 'link'; 29 | } 30 | 31 | if (!isset($this->render)) { 32 | $this->render = new JsExpression('function render(data, type, row, meta){ 33 | var p = ' . Json::encode($this->queryParams) . '; 34 | var q = {};for (var i = 0; i < p.length; i++) {q[p[i]] = row[p[i]];} 35 | var link = jQuery(\'' . Html::a($this->label, $this->url, $this->linkOptions) . '\'); 36 | var paramPrefix = ((link.attr("href").indexOf("?") < 0) ? "?" : "&"); 37 | link.attr("id", link.attr("id") + meta.row);link.attr("href", link.attr("href") + paramPrefix + jQuery.param(q)); 38 | return link.get()[0].outerHTML;}'); 39 | } 40 | 41 | parent::init(); 42 | } 43 | 44 | /** 45 | * @return array 46 | */ 47 | public function getExtraColumns() 48 | { 49 | return array_unique(array_merge(parent::getExtraColumns(), $this->queryParams)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/assets/DataTableAsset.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable\assets; 9 | 10 | 11 | use yii\web\AssetBundle; 12 | 13 | class DataTableAsset extends AssetBundle 14 | { 15 | const STYLING_DEFAULT = 'default'; 16 | const STYLING_BOOTSTRAP = 'bootstrap'; 17 | const STYLING_JUI = 'jqueryui'; 18 | 19 | public $styling = self::STYLING_DEFAULT; 20 | public $fontAwesome = false; 21 | 22 | public $depends = [ 23 | 'yii\web\JqueryAsset', 24 | ]; 25 | 26 | public function init() 27 | { 28 | parent::init(); 29 | 30 | switch ($this->styling) { 31 | case self::STYLING_JUI: 32 | $this->depends[] = DataTableJuiAsset::class; 33 | break; 34 | case self::STYLING_BOOTSTRAP: 35 | $this->depends[] = DataTableBootstrapAsset::class; 36 | break; 37 | case self::STYLING_DEFAULT: 38 | $this->depends[] = DataTableBaseAsset::class; 39 | break; 40 | default; 41 | } 42 | 43 | if ($this->fontAwesome) { 44 | $this->depends[] = DataTableFaAsset::class; 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/assets/DataTableBaseAsset.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable\assets; 9 | 10 | 11 | use yii\web\AssetBundle; 12 | 13 | class DataTableBaseAsset extends AssetBundle 14 | { 15 | const STYLING_DEFAULT = 'default'; 16 | const STYLING_BOOTSTRAP = 'bootstrap'; 17 | const STYLING_JUI = 'jqueryui'; 18 | 19 | public $styling = self::STYLING_DEFAULT; 20 | public $fontAwesome = false; 21 | public $sourcePath = '@bower/datatables/media'; 22 | 23 | public $depends = [ 24 | 'yii\web\JqueryAsset', 25 | ]; 26 | 27 | public function init() 28 | { 29 | parent::init(); 30 | $this->js[] = 'js/jquery.dataTables' . (YII_ENV_DEV ? '' : '.min') . '.js'; 31 | $this->css[] = 'css/jquery.dataTables' . (YII_ENV_DEV ? '' : '.min') . '.css'; 32 | 33 | if ($this->fontAwesome) { 34 | $this->css[] = 'dataTables.fontAwesome.css'; 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/assets/DataTableBootstrapAsset.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable\assets; 9 | 10 | 11 | use yii\web\AssetBundle; 12 | 13 | class DataTableBootstrapAsset extends AssetBundle 14 | { 15 | public $depends = [ 16 | DataTableBaseAsset::class, 17 | ]; 18 | 19 | public function init() 20 | { 21 | parent::init(); 22 | 23 | if (class_exists('yii\bootstrap\BootstrapAsset')) { 24 | $this->sourcePath = '@bower/datatables-plugins/integration/bootstrap/3'; 25 | $this->depends[] = 'yii\bootstrap\BootstrapAsset'; 26 | $this->css[] = 'dataTables.bootstrap.css'; 27 | $this->js[] = 'dataTables.bootstrap' . (YII_ENV_DEV ? '' : '.min') . '.js'; 28 | 29 | } else if(class_exists('yii\bootstrap4\BootstrapAsset')) { 30 | $this->sourcePath = '@bower/datatables.net-bs4'; 31 | $this->depends[] = 'yii\bootstrap4\BootstrapAsset'; 32 | $this->css[] = 'css\dataTables.bootstrap4.css'; 33 | $this->js[] = 'js\dataTables.bootstrap4' . (YII_ENV_DEV ? '' : '.min') . '.js'; 34 | 35 | } else { 36 | $this->sourcePath = '@npm/datatables.net-bs5'; 37 | $this->depends[] = 'yii\bootstrap5\BootstrapAsset'; 38 | $this->css[] = 'css\dataTables.bootstrap5.css'; 39 | $this->js[] = 'js\dataTables.bootstrap5' . (YII_ENV_DEV ? '' : '.min') . '.js'; 40 | } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/assets/DataTableDefaultAsset.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable\assets; 9 | 10 | 11 | use yii\web\AssetBundle; 12 | 13 | class DataTableDefaultAsset extends AssetBundle 14 | { 15 | public $sourcePath = '@bower/datatables/media/css'; 16 | 17 | public $depends = [ 18 | DataTableBaseAsset::class, 19 | ]; 20 | 21 | } -------------------------------------------------------------------------------- /src/assets/DataTableFaAsset.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable\assets; 9 | 10 | 11 | use yii\web\AssetBundle; 12 | 13 | class DataTableFaAsset extends AssetBundle 14 | { 15 | public $css = [ 16 | 'dataTables.fontAwesome.css', 17 | ]; 18 | 19 | public $depends = [ 20 | DataTableBaseAsset::class, 21 | ]; 22 | } -------------------------------------------------------------------------------- /src/assets/DataTableJuiAsset.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace nullref\datatable\assets; 9 | 10 | 11 | use yii\web\AssetBundle; 12 | 13 | class DataTableJuiAsset extends AssetBundle 14 | { 15 | public $sourcePath = '@bower/datatables-plugins/integration/jqueryui'; 16 | 17 | public $depends = [ 18 | DataTableBaseAsset::class, 19 | ]; 20 | 21 | public function init() 22 | { 23 | parent::init(); 24 | 25 | $this->depends[] = 'yii\jui\JuiAsset'; 26 | $this->css[] = 'datatables-plugins/integration/jqueryui/dataTables.jqueryui.css'; 27 | $this->js[] = 'datatables-plugins/integration/jqueryui/dataTables.jqueryui' . (YII_ENV_DEV ? '' : '.min') . '.js'; 28 | } 29 | 30 | } --------------------------------------------------------------------------------