Grid.php 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. <?php
  2. namespace Dcat\Admin;
  3. use Closure;
  4. use Dcat\Admin\Contracts\Repository;
  5. use Dcat\Admin\Grid\Column;
  6. use Dcat\Admin\Grid\Concerns;
  7. use Dcat\Admin\Grid\Model;
  8. use Dcat\Admin\Grid\Row;
  9. use Dcat\Admin\Grid\Tools;
  10. use Dcat\Admin\Support\Helper;
  11. use Dcat\Admin\Traits\HasBuilderEvents;
  12. use Dcat\Admin\Traits\HasVariables;
  13. use Illuminate\Contracts\Support\Renderable;
  14. use Illuminate\Database\Eloquent\Builder;
  15. use Illuminate\Support\Collection;
  16. use Illuminate\Support\Traits\Macroable;
  17. class Grid
  18. {
  19. use HasBuilderEvents;
  20. use HasVariables;
  21. use Concerns\HasEvents;
  22. use Concerns\HasNames;
  23. use Concerns\HasFilter;
  24. use Concerns\HasTools;
  25. use Concerns\HasActions;
  26. use Concerns\HasPaginator;
  27. use Concerns\HasExporter;
  28. use Concerns\HasComplexHeaders;
  29. use Concerns\HasSelector;
  30. use Concerns\HasQuickCreate;
  31. use Concerns\HasQuickSearch;
  32. use Concerns\CanFixColumns;
  33. use Concerns\CanHidesColumns;
  34. use Macroable {
  35. __call as macroCall;
  36. }
  37. const CREATE_MODE_DEFAULT = 'default';
  38. const CREATE_MODE_DIALOG = 'dialog';
  39. const ASYNC_NAME = '_async_';
  40. /**
  41. * The grid data model instance.
  42. *
  43. * @var \Dcat\Admin\Grid\Model
  44. */
  45. protected $model;
  46. /**
  47. * Collection of grid columns.
  48. *
  49. * @var \Illuminate\Support\Collection
  50. */
  51. protected $columns;
  52. /**
  53. * Collection of all grid columns.
  54. *
  55. * @var \Illuminate\Support\Collection
  56. */
  57. protected $allColumns;
  58. /**
  59. * Collection of all data rows.
  60. *
  61. * @var \Illuminate\Support\Collection
  62. */
  63. protected $rows;
  64. /**
  65. * @var array
  66. */
  67. protected $rowsCallbacks = [];
  68. /**
  69. * All column names of the grid.
  70. *
  71. * @var array
  72. */
  73. protected $columnNames = [];
  74. /**
  75. * Grid builder.
  76. *
  77. * @var \Closure
  78. */
  79. protected $builder;
  80. /**
  81. * Mark if the grid is built.
  82. *
  83. * @var bool
  84. */
  85. protected $built = false;
  86. /**
  87. * Resource path of the grid.
  88. *
  89. * @var
  90. */
  91. protected $resourcePath;
  92. /**
  93. * Default primary key name.
  94. *
  95. * @var string|array
  96. */
  97. protected $keyName;
  98. /**
  99. * View for grid to render.
  100. *
  101. * @var string
  102. */
  103. protected $view = 'admin::grid.table';
  104. /**
  105. * @var Closure[]
  106. */
  107. protected $header = [];
  108. /**
  109. * @var Closure[]
  110. */
  111. protected $footer = [];
  112. /**
  113. * @var Closure
  114. */
  115. protected $wrapper;
  116. /**
  117. * @var bool
  118. */
  119. protected $addNumberColumn = false;
  120. /**
  121. * @var string
  122. */
  123. protected $tableId = 'grid-table';
  124. /**
  125. * @var Grid\Tools\RowSelector
  126. */
  127. protected $rowSelector;
  128. /**
  129. * Options for grid.
  130. *
  131. * @var array
  132. */
  133. protected $options = [
  134. 'pagination' => true,
  135. 'filter' => true,
  136. 'actions' => true,
  137. 'quick_edit_button' => false,
  138. 'edit_button' => true,
  139. 'view_button' => true,
  140. 'delete_button' => true,
  141. 'row_selector' => true,
  142. 'create_button' => true,
  143. 'bordered' => false,
  144. 'table_collapse' => true,
  145. 'toolbar' => true,
  146. 'create_mode' => self::CREATE_MODE_DEFAULT,
  147. 'dialog_form_area' => ['700px', '670px'],
  148. 'table_class' => ['table', 'custom-data-table', 'data-table'],
  149. 'scrollbar_x' => false,
  150. 'actions_class' => null,
  151. 'batch_actions_class' => null,
  152. 'paginator_class' => null,
  153. ];
  154. /**
  155. * @var \Illuminate\Http\Request
  156. */
  157. protected $request;
  158. /**
  159. * @var bool
  160. */
  161. protected $show = true;
  162. /**
  163. * @var bool
  164. */
  165. protected $async = false;
  166. /**
  167. * Create a new grid instance.
  168. *
  169. * Grid constructor.
  170. *
  171. * @param Repository|\Illuminate\Database\Eloquent\Model|Builder|null $repository
  172. * @param null|\Closure $builder
  173. */
  174. public function __construct($repository = null, ?\Closure $builder = null, $request = null)
  175. {
  176. $this->model = new Model(request(), $repository);
  177. $this->columns = new Collection();
  178. $this->allColumns = new Collection();
  179. $this->rows = new Collection();
  180. $this->builder = $builder;
  181. $this->request = $request ?: request();
  182. $this->resourcePath = url($this->request->getPathInfo());
  183. if ($repository = $this->model->repository()) {
  184. $this->setKeyName($repository->getKeyName());
  185. }
  186. $this->model->setGrid($this);
  187. $this->setUpTools();
  188. $this->setUpFilter();
  189. $this->callResolving();
  190. }
  191. /**
  192. * Get table ID.
  193. *
  194. * @return string
  195. */
  196. public function getTableId()
  197. {
  198. return $this->tableId;
  199. }
  200. /**
  201. * Set primary key name.
  202. *
  203. * @param string|array $name
  204. *
  205. * @return $this
  206. */
  207. public function setKeyName($name)
  208. {
  209. $this->keyName = $name;
  210. return $this;
  211. }
  212. /**
  213. * Get or set primary key name.
  214. *
  215. * @return string|array
  216. */
  217. public function getKeyName()
  218. {
  219. return $this->keyName ?: 'id';
  220. }
  221. /**
  222. * Add column to Grid.
  223. *
  224. * @param string $name
  225. * @param string $label
  226. *
  227. * @return Column
  228. */
  229. public function column($name, $label = '')
  230. {
  231. return $this->addColumn($name, $label);
  232. }
  233. /**
  234. * Add number column.
  235. *
  236. * @param null|string $label
  237. *
  238. * @return Column
  239. */
  240. public function number(?string $label = null)
  241. {
  242. return $this->addColumn('#', $label ?: '#');
  243. }
  244. /**
  245. * 启用异步渲染功能.
  246. *
  247. * @param bool $async
  248. *
  249. * @return $this
  250. */
  251. public function async(bool $async = true)
  252. {
  253. $this->async = $async;
  254. if ($async) {
  255. $this->view('admin::grid.async-table');
  256. }
  257. return $this;
  258. }
  259. public function getAsync()
  260. {
  261. return $this->async;
  262. }
  263. /**
  264. * 判断是否允许查询数据.
  265. *
  266. * @return bool
  267. */
  268. public function buildable()
  269. {
  270. return ! $this->async || $this->isAsyncRequest();
  271. }
  272. /**
  273. * @return bool
  274. */
  275. public function isAsyncRequest()
  276. {
  277. return $this->request->get(static::ASYNC_NAME);
  278. }
  279. /**
  280. * Batch add column to grid.
  281. *
  282. * @example
  283. * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);
  284. * 2.$grid->columns('name', 'email' ...)
  285. *
  286. * @param array $columns
  287. *
  288. * @return Collection|Column[]|void
  289. */
  290. public function columns($columns = null)
  291. {
  292. if ($columns === null) {
  293. return $this->columns;
  294. }
  295. if (func_num_args() == 1 && is_array($columns)) {
  296. foreach ($columns as $column => $label) {
  297. $this->column($column, $label);
  298. }
  299. return;
  300. }
  301. foreach (func_get_args() as $column) {
  302. $this->column($column);
  303. }
  304. }
  305. /**
  306. * @return Collection|Column[]
  307. */
  308. public function allColumns()
  309. {
  310. return $this->allColumns;
  311. }
  312. /**
  313. * 删除列.
  314. *
  315. * @param string|Column $column
  316. *
  317. * @return $this
  318. */
  319. public function dropColumn($column)
  320. {
  321. if ($column instanceof Column) {
  322. $column = $column->getName();
  323. }
  324. $this->columns->offsetUnset($column);
  325. $this->allColumns->offsetUnset($column);
  326. return $this;
  327. }
  328. /**
  329. * Add column to grid.
  330. *
  331. * @param string $field
  332. * @param string $label
  333. *
  334. * @return Column
  335. */
  336. protected function addColumn($field = '', $label = '')
  337. {
  338. $column = $this->newColumn($field, $label);
  339. $this->columns->put($field, $column);
  340. $this->allColumns->put($field, $column);
  341. return $column;
  342. }
  343. /**
  344. * @param string $field
  345. * @param string $label
  346. *
  347. * @return Column
  348. */
  349. public function prependColumn($field = '', $label = '')
  350. {
  351. $column = $this->newColumn($field, $label);
  352. $this->columns->prepend($column, $field);
  353. $this->allColumns->prepend($column, $field);
  354. return $column;
  355. }
  356. /**
  357. * @param string $field
  358. * @param string $label
  359. *
  360. * @return Column
  361. */
  362. public function newColumn($field = '', $label = '')
  363. {
  364. $column = new Column($field, $label);
  365. $column->setGrid($this);
  366. return $column;
  367. }
  368. /**
  369. * Get Grid model.
  370. *
  371. * @return Model
  372. */
  373. public function model()
  374. {
  375. return $this->model;
  376. }
  377. /**
  378. * @return array
  379. */
  380. public function getColumnNames()
  381. {
  382. return $this->columnNames;
  383. }
  384. /**
  385. * Apply column filter to grid query.
  386. */
  387. protected function applyColumnFilter()
  388. {
  389. $this->columns->each->bindFilterQuery($this->model());
  390. }
  391. /**
  392. * @param string|array $class
  393. *
  394. * @return $this
  395. */
  396. public function addTableClass($class)
  397. {
  398. $this->options['table_class'] = array_merge((array) $this->options['table_class'], (array) $class);
  399. return $this;
  400. }
  401. public function formatTableClass()
  402. {
  403. if ($this->options['bordered']) {
  404. $this->addTableClass(['table-bordered', 'complex-headers', 'data-table']);
  405. }
  406. return implode(' ', array_unique((array) $this->options['table_class']));
  407. }
  408. /**
  409. * Build the grid.
  410. *
  411. * @return void
  412. */
  413. public function build()
  414. {
  415. if (! $this->buildable()) {
  416. $this->callBuilder();
  417. $this->handleExportRequest();
  418. $this->prependRowSelectorColumn();
  419. $this->appendActionsColumn();
  420. $this->sortHeaders();
  421. return;
  422. }
  423. if ($this->built) {
  424. return;
  425. }
  426. $collection = clone $this->processFilter();
  427. $this->prependRowSelectorColumn();
  428. $this->appendActionsColumn();
  429. Column::setOriginalGridModels($collection);
  430. $this->columns->map(function (Column $column) use (&$collection) {
  431. $column->fill($collection);
  432. $this->columnNames[] = $column->getName();
  433. });
  434. $this->buildRows($collection);
  435. $this->sortHeaders();
  436. }
  437. /**
  438. * @return void
  439. */
  440. public function callBuilder()
  441. {
  442. if ($this->builder && ! $this->built) {
  443. call_user_func($this->builder, $this);
  444. }
  445. $this->built = true;
  446. }
  447. /**
  448. * Build the grid rows.
  449. *
  450. * @param Collection $data
  451. *
  452. * @return void
  453. */
  454. protected function buildRows($data)
  455. {
  456. $this->rows = $data->map(function ($row) {
  457. return new Row($this, $row);
  458. });
  459. foreach ($this->rowsCallbacks as $callback) {
  460. $callback($this->rows);
  461. }
  462. }
  463. /**
  464. * Set grid row callback function.
  465. *
  466. * @return Collection|$this
  467. */
  468. public function rows(\Closure $callback = null)
  469. {
  470. if ($callback) {
  471. $this->rowsCallbacks[] = $callback;
  472. return $this;
  473. }
  474. return $this->rows;
  475. }
  476. /**
  477. * Get create url.
  478. *
  479. * @return string
  480. */
  481. public function getCreateUrl()
  482. {
  483. return $this->urlWithConstraints($this->resource().'/create');
  484. }
  485. /**
  486. * @param string $key
  487. *
  488. * @return string
  489. */
  490. public function getEditUrl($key)
  491. {
  492. return $this->urlWithConstraints("{$this->resource()}/{$key}/edit");
  493. }
  494. /**
  495. * @param string $url
  496. *
  497. * @return string
  498. */
  499. public function urlWithConstraints(?string $url)
  500. {
  501. $queryString = '';
  502. if ($constraints = $this->model()->getConstraints()) {
  503. $queryString = http_build_query($constraints);
  504. }
  505. return $url.($queryString ? ('?'.$queryString) : '');
  506. }
  507. /**
  508. * @param \Closure $closure
  509. *
  510. * @return Grid\Tools\RowSelector
  511. */
  512. public function rowSelector()
  513. {
  514. return $this->rowSelector ?: ($this->rowSelector = new Grid\Tools\RowSelector($this));
  515. }
  516. /**
  517. * Prepend checkbox column for grid.
  518. *
  519. * @return void
  520. */
  521. protected function prependRowSelectorColumn()
  522. {
  523. if (! $this->options['row_selector']) {
  524. return;
  525. }
  526. $rowSelector = $this->rowSelector();
  527. $keyName = $this->getKeyName();
  528. $this->prependColumn(
  529. Grid\Column::SELECT_COLUMN_NAME
  530. )->setLabel($rowSelector->renderHeader())->display(function () use ($rowSelector, $keyName) {
  531. return $rowSelector->renderColumn($this, $this->{$keyName});
  532. });
  533. }
  534. /**
  535. * @param string $width
  536. * @param string $height
  537. *
  538. * @return $this
  539. */
  540. public function setDialogFormDimensions(string $width, string $height)
  541. {
  542. $this->options['dialog_form_area'] = [$width, $height];
  543. return $this;
  544. }
  545. /**
  546. * Render create button for grid.
  547. *
  548. * @return string
  549. */
  550. public function renderCreateButton()
  551. {
  552. if (! $this->options['create_button']) {
  553. return '';
  554. }
  555. return (new Tools\CreateButton($this))->render();
  556. }
  557. /**
  558. * @param bool $value
  559. *
  560. * @return $this
  561. */
  562. public function withBorder(bool $value = true)
  563. {
  564. $this->options['bordered'] = $value;
  565. return $this;
  566. }
  567. /**
  568. * @param bool $value
  569. *
  570. * @return $this
  571. */
  572. public function tableCollapse(bool $value = true)
  573. {
  574. $this->options['table_collapse'] = $value;
  575. return $this;
  576. }
  577. /**
  578. * 显示横轴滚动条.
  579. *
  580. * @param bool $value
  581. *
  582. * @return $this
  583. */
  584. public function scrollbar(bool $value = true)
  585. {
  586. $this->options['table_scrollbar'] = $value;
  587. return $this;
  588. }
  589. /**
  590. * Set grid header.
  591. *
  592. * @param Closure|string|Renderable $content
  593. *
  594. * @return $this
  595. */
  596. public function header($content)
  597. {
  598. $this->header[] = $content;
  599. return $this;
  600. }
  601. /**
  602. * Render grid header.
  603. *
  604. * @return string
  605. */
  606. public function renderHeader()
  607. {
  608. if (! $this->header) {
  609. return '';
  610. }
  611. return <<<HTML
  612. <div class="card-header clearfix" style="border-bottom: 0;background: transparent;padding: 0">{$this->renderHeaderOrFooter($this->header)}</div>
  613. HTML;
  614. }
  615. protected function renderHeaderOrFooter($callbacks)
  616. {
  617. $target = [$this->processFilter(), $this];
  618. $content = [];
  619. foreach ($callbacks as $callback) {
  620. $content[] = Helper::render($callback, $target);
  621. }
  622. if (empty($content)) {
  623. return '';
  624. }
  625. return implode('<div class="mb-1 clearfix"></div>', $content);
  626. }
  627. /**
  628. * Set grid footer.
  629. *
  630. * @param Closure|string|Renderable $content
  631. *
  632. * @return $this
  633. */
  634. public function footer($content)
  635. {
  636. $this->footer[] = $content;
  637. return $this;
  638. }
  639. /**
  640. * Render grid footer.
  641. *
  642. * @return string
  643. */
  644. public function renderFooter()
  645. {
  646. if (! $this->footer) {
  647. return '';
  648. }
  649. return <<<HTML
  650. <div class="box-footer clearfix">{$this->renderHeaderOrFooter($this->footer)}</div>
  651. HTML;
  652. }
  653. /**
  654. * Get or set option for grid.
  655. *
  656. * @param string|array $key
  657. * @param mixed $value
  658. *
  659. * @return $this|mixed
  660. */
  661. public function option($key, $value = null)
  662. {
  663. if (is_null($value)) {
  664. return $this->options[$key] ?? null;
  665. }
  666. if (is_array($key)) {
  667. $this->options = array_merge($this->options, $key);
  668. } else {
  669. $this->options[$key] = $value;
  670. }
  671. return $this;
  672. }
  673. protected function setUpOptions()
  674. {
  675. if ($this->options['bordered']) {
  676. $this->tableCollapse(false);
  677. }
  678. }
  679. /**
  680. * Disable row selector.
  681. *
  682. * @return $this
  683. */
  684. public function disableRowSelector(bool $disable = true)
  685. {
  686. $this->tools->disableBatchActions($disable);
  687. return $this->option('row_selector', ! $disable);
  688. }
  689. /**
  690. * Show row selector.
  691. *
  692. * @return $this
  693. */
  694. public function showRowSelector(bool $val = true)
  695. {
  696. return $this->disableRowSelector(! $val);
  697. }
  698. /**
  699. * Remove create button on grid.
  700. *
  701. * @return $this
  702. */
  703. public function disableCreateButton(bool $disable = true)
  704. {
  705. return $this->option('create_button', ! $disable);
  706. }
  707. /**
  708. * Show create button.
  709. *
  710. * @return $this
  711. */
  712. public function showCreateButton(bool $val = true)
  713. {
  714. return $this->disableCreateButton(! $val);
  715. }
  716. /**
  717. * If allow creation.
  718. *
  719. * @return bool
  720. */
  721. public function allowCreateButton()
  722. {
  723. return $this->options['create_button'];
  724. }
  725. /**
  726. * @param string $mode
  727. *
  728. * @return $this
  729. */
  730. public function createMode(string $mode)
  731. {
  732. return $this->option('create_mode', $mode);
  733. }
  734. /**
  735. * @return $this
  736. */
  737. public function enableDialogCreate()
  738. {
  739. return $this->createMode(self::CREATE_MODE_DIALOG);
  740. }
  741. /**
  742. * Get or set resource path.
  743. *
  744. * @return string
  745. */
  746. public function resource()
  747. {
  748. return $this->resourcePath;
  749. }
  750. /**
  751. * Create a grid instance.
  752. *
  753. * @param mixed ...$params
  754. *
  755. * @return $this
  756. */
  757. public static function make(...$params)
  758. {
  759. return new static(...$params);
  760. }
  761. /**
  762. * @param Closure $closure
  763. *
  764. * @return $this;
  765. */
  766. public function wrap(\Closure $closure)
  767. {
  768. $this->wrapper = $closure;
  769. return $this;
  770. }
  771. /**
  772. * @return bool
  773. */
  774. public function hasWrapper()
  775. {
  776. return $this->wrapper ? true : false;
  777. }
  778. /**
  779. * Add variables to grid view.
  780. *
  781. * @param array $variables
  782. *
  783. * @return $this
  784. */
  785. public function with(array $variables)
  786. {
  787. return $this->addVariables($variables);
  788. }
  789. /**
  790. * Get all variables will used in grid view.
  791. *
  792. * @return array
  793. */
  794. protected function defaultVariables()
  795. {
  796. return [
  797. 'grid' => $this,
  798. 'tableId' => $this->getTableId(),
  799. ];
  800. }
  801. /**
  802. * Set a view to render.
  803. *
  804. * @param string $view
  805. *
  806. * @return $this
  807. */
  808. public function view($view)
  809. {
  810. $this->view = $view;
  811. return $this;
  812. }
  813. /**
  814. * Set grid title.
  815. *
  816. * @param string $title
  817. *
  818. * @return $this
  819. */
  820. public function title($title)
  821. {
  822. $this->variables['title'] = $title;
  823. return $this;
  824. }
  825. /**
  826. * Set grid description.
  827. *
  828. * @param string $description
  829. *
  830. * @return $this
  831. */
  832. public function description($description)
  833. {
  834. $this->variables['description'] = $description;
  835. return $this;
  836. }
  837. /**
  838. * Set resource path for grid.
  839. *
  840. * @param string $path
  841. *
  842. * @return $this
  843. */
  844. public function setResource($path)
  845. {
  846. $this->resourcePath = admin_url($path);
  847. return $this;
  848. }
  849. /**
  850. * 设置是否显示.
  851. *
  852. * @param bool $value
  853. *
  854. * @return $this
  855. */
  856. public function show(bool $value = true)
  857. {
  858. $this->show = $value;
  859. return $this;
  860. }
  861. /**
  862. * 是否显示横向滚动条.
  863. *
  864. * @param bool $value
  865. *
  866. * @return $this
  867. */
  868. public function scrollbarX(bool $value = true)
  869. {
  870. $this->options['scrollbar_x'] = $value;
  871. return $this;
  872. }
  873. /**
  874. * @return string
  875. */
  876. public function formatTableParentClass()
  877. {
  878. $tableCollaps = $this->option('table_collapse') ? 'table-collapse' : '';
  879. $scrollbarX = $this->option('scrollbar_x') ? 'table-scrollbar-x' : '';
  880. return "table-responsive table-wrapper complex-container table-middle mt-1 {$tableCollaps} {$scrollbarX}";
  881. }
  882. /**
  883. * Get the string contents of the grid view.
  884. *
  885. * @return string
  886. */
  887. public function render()
  888. {
  889. $this->callComposing();
  890. $this->build();
  891. $this->applyFixColumns();
  892. $this->setUpOptions();
  893. $this->addFilterScript();
  894. $this->addScript();
  895. return $this->doWrap();
  896. }
  897. public function getView()
  898. {
  899. if ($this->async && $this->hasFixColumns()) {
  900. return 'admin::grid.async-fixed-table';
  901. }
  902. return $this->view;
  903. }
  904. protected function addScript()
  905. {
  906. if ($this->async && ! $this->isAsyncRequest()) {
  907. $query = static::ASYNC_NAME;
  908. $url = Helper::fullUrlWithoutQuery(['_pjax']);
  909. $url = Helper::urlWithQuery($url, [static::ASYNC_NAME => 1]);
  910. $options = [
  911. 'selector' => ".async-{$this->getTableId()}",
  912. 'queryName' => $query,
  913. 'url' => $url,
  914. ];
  915. if ($this->hasFixColumns()) {
  916. $options['loadingStyle'] = 'height:140px;';
  917. }
  918. $options = json_encode($options);
  919. Admin::script(
  920. <<<JS
  921. Dcat.grid.async({$options}).render()
  922. JS
  923. );
  924. }
  925. }
  926. /**
  927. * @return string
  928. */
  929. protected function doWrap()
  930. {
  931. if (! $this->show) {
  932. return;
  933. }
  934. $view = view($this->getView(), $this->variables());
  935. if (! $wrapper = $this->wrapper) {
  936. return $view->render();
  937. }
  938. return Helper::render($wrapper($view));
  939. }
  940. /**
  941. * Add column to grid.
  942. *
  943. * @param string $name
  944. *
  945. * @return Column
  946. */
  947. public function __get($name)
  948. {
  949. return $this->addColumn($name);
  950. }
  951. /**
  952. * Dynamically add columns to the grid view.
  953. *
  954. * @param $method
  955. * @param $arguments
  956. *
  957. * @return Column
  958. */
  959. public function __call($method, $arguments)
  960. {
  961. if (static::hasMacro($method)) {
  962. return $this->macroCall($method, $arguments);
  963. }
  964. return $this->addColumn($method, $arguments[0] ?? null);
  965. }
  966. public function __toString()
  967. {
  968. return (string) $this->render();
  969. }
  970. }