Grid.php 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  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. * @return $this
  205. */
  206. public function setKeyName($name)
  207. {
  208. $this->keyName = $name;
  209. return $this;
  210. }
  211. /**
  212. * Get or set primary key name.
  213. *
  214. * @return string|array
  215. */
  216. public function getKeyName()
  217. {
  218. return $this->keyName ?: 'id';
  219. }
  220. /**
  221. * Add column to Grid.
  222. *
  223. * @param string $name
  224. * @param string $label
  225. * @return Column
  226. */
  227. public function column($name, $label = '')
  228. {
  229. return $this->addColumn($name, $label);
  230. }
  231. /**
  232. * Add number column.
  233. *
  234. * @param null|string $label
  235. * @return Column
  236. */
  237. public function number(?string $label = null)
  238. {
  239. return $this->addColumn('#', $label ?: '#');
  240. }
  241. /**
  242. * 启用异步渲染功能.
  243. *
  244. * @param bool $async
  245. * @return $this
  246. */
  247. public function async(bool $async = true)
  248. {
  249. $this->async = $async;
  250. if ($async) {
  251. $this->view('admin::grid.async-table');
  252. }
  253. return $this;
  254. }
  255. public function getAsync()
  256. {
  257. return $this->async;
  258. }
  259. /**
  260. * 判断是否允许查询数据.
  261. *
  262. * @return bool
  263. */
  264. public function buildable()
  265. {
  266. return ! $this->async || $this->isAsyncRequest();
  267. }
  268. /**
  269. * @return bool
  270. */
  271. public function isAsyncRequest()
  272. {
  273. return $this->request->get(static::ASYNC_NAME);
  274. }
  275. /**
  276. * Batch add column to grid.
  277. *
  278. * @example
  279. * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);
  280. * 2.$grid->columns('name', 'email' ...)
  281. *
  282. * @param array $columns
  283. * @return Collection|Column[]|void
  284. */
  285. public function columns($columns = null)
  286. {
  287. if ($columns === null) {
  288. return $this->columns;
  289. }
  290. if (func_num_args() == 1 && is_array($columns)) {
  291. foreach ($columns as $column => $label) {
  292. $this->column($column, $label);
  293. }
  294. return;
  295. }
  296. foreach (func_get_args() as $column) {
  297. $this->column($column);
  298. }
  299. }
  300. /**
  301. * @return Collection|Column[]
  302. */
  303. public function allColumns()
  304. {
  305. return $this->allColumns;
  306. }
  307. /**
  308. * 删除列.
  309. *
  310. * @param string|Column $column
  311. * @return $this
  312. */
  313. public function dropColumn($column)
  314. {
  315. if ($column instanceof Column) {
  316. $column = $column->getName();
  317. }
  318. $this->columns->offsetUnset($column);
  319. $this->allColumns->offsetUnset($column);
  320. return $this;
  321. }
  322. /**
  323. * Add column to grid.
  324. *
  325. * @param string $field
  326. * @param string $label
  327. * @return Column
  328. */
  329. protected function addColumn($field = '', $label = '')
  330. {
  331. $column = $this->newColumn($field, $label);
  332. $this->columns->put($field, $column);
  333. $this->allColumns->put($field, $column);
  334. return $column;
  335. }
  336. /**
  337. * @param string $field
  338. * @param string $label
  339. * @return Column
  340. */
  341. public function prependColumn($field = '', $label = '')
  342. {
  343. $column = $this->newColumn($field, $label);
  344. $this->columns->prepend($column, $field);
  345. $this->allColumns->prepend($column, $field);
  346. return $column;
  347. }
  348. /**
  349. * @param string $field
  350. * @param string $label
  351. * @return Column
  352. */
  353. public function newColumn($field = '', $label = '')
  354. {
  355. $column = new Column($field, $label);
  356. $column->setGrid($this);
  357. return $column;
  358. }
  359. /**
  360. * Get Grid model.
  361. *
  362. * @return Model
  363. */
  364. public function model()
  365. {
  366. return $this->model;
  367. }
  368. /**
  369. * @return array
  370. */
  371. public function getColumnNames()
  372. {
  373. return $this->columnNames;
  374. }
  375. /**
  376. * Apply column filter to grid query.
  377. */
  378. protected function applyColumnFilter()
  379. {
  380. $this->columns->each->bindFilterQuery($this->model());
  381. }
  382. /**
  383. * @param string|array $class
  384. * @return $this
  385. */
  386. public function addTableClass($class)
  387. {
  388. $this->options['table_class'] = array_merge((array) $this->options['table_class'], (array) $class);
  389. return $this;
  390. }
  391. public function formatTableClass()
  392. {
  393. if ($this->options['bordered']) {
  394. $this->addTableClass(['table-bordered', 'complex-headers', 'data-table']);
  395. }
  396. return implode(' ', array_unique((array) $this->options['table_class']));
  397. }
  398. /**
  399. * Build the grid.
  400. *
  401. * @return void
  402. */
  403. public function build()
  404. {
  405. if (! $this->buildable()) {
  406. $this->callBuilder();
  407. $this->handleExportRequest();
  408. $this->prependRowSelectorColumn();
  409. $this->appendActionsColumn();
  410. $this->sortHeaders();
  411. return;
  412. }
  413. if ($this->built) {
  414. return;
  415. }
  416. $collection = clone $this->processFilter();
  417. $this->prependRowSelectorColumn();
  418. $this->appendActionsColumn();
  419. Column::setOriginalGridModels($collection);
  420. $this->columns->map(function (Column $column) use (&$collection) {
  421. $column->fill($collection);
  422. $this->columnNames[] = $column->getName();
  423. });
  424. $this->buildRows($collection);
  425. $this->sortHeaders();
  426. }
  427. /**
  428. * @return void
  429. */
  430. public function callBuilder()
  431. {
  432. if ($this->builder && ! $this->built) {
  433. call_user_func($this->builder, $this);
  434. }
  435. $this->built = true;
  436. }
  437. /**
  438. * Build the grid rows.
  439. *
  440. * @param Collection $data
  441. * @return void
  442. */
  443. protected function buildRows($data)
  444. {
  445. $this->rows = $data->map(function ($row) {
  446. return new Row($this, $row);
  447. });
  448. foreach ($this->rowsCallbacks as $callback) {
  449. $callback($this->rows);
  450. }
  451. }
  452. /**
  453. * Set grid row callback function.
  454. *
  455. * @return Collection|$this
  456. */
  457. public function rows(\Closure $callback = null)
  458. {
  459. if ($callback) {
  460. $this->rowsCallbacks[] = $callback;
  461. return $this;
  462. }
  463. return $this->rows;
  464. }
  465. /**
  466. * Get create url.
  467. *
  468. * @return string
  469. */
  470. public function getCreateUrl()
  471. {
  472. return $this->urlWithConstraints($this->resource().'/create');
  473. }
  474. /**
  475. * @param string $key
  476. * @return string
  477. */
  478. public function getEditUrl($key)
  479. {
  480. return $this->urlWithConstraints("{$this->resource()}/{$key}/edit");
  481. }
  482. /**
  483. * @param string $url
  484. * @return string
  485. */
  486. public function urlWithConstraints(?string $url)
  487. {
  488. $queryString = '';
  489. if ($constraints = $this->model()->getConstraints()) {
  490. $queryString = http_build_query($constraints);
  491. }
  492. return $url.($queryString ? ('?'.$queryString) : '');
  493. }
  494. /**
  495. * @param \Closure $closure
  496. * @return Grid\Tools\RowSelector
  497. */
  498. public function rowSelector()
  499. {
  500. return $this->rowSelector ?: ($this->rowSelector = new Grid\Tools\RowSelector($this));
  501. }
  502. /**
  503. * Prepend checkbox column for grid.
  504. *
  505. * @return void
  506. */
  507. protected function prependRowSelectorColumn()
  508. {
  509. if (! $this->options['row_selector']) {
  510. return;
  511. }
  512. $rowSelector = $this->rowSelector();
  513. $keyName = $this->getKeyName();
  514. $this->prependColumn(
  515. Grid\Column::SELECT_COLUMN_NAME
  516. )->setLabel($rowSelector->renderHeader())->display(function () use ($rowSelector, $keyName) {
  517. return $rowSelector->renderColumn($this, $this->{$keyName});
  518. });
  519. }
  520. /**
  521. * @param string $width
  522. * @param string $height
  523. * @return $this
  524. */
  525. public function setDialogFormDimensions(string $width, string $height)
  526. {
  527. $this->options['dialog_form_area'] = [$width, $height];
  528. return $this;
  529. }
  530. /**
  531. * Render create button for grid.
  532. *
  533. * @return string
  534. */
  535. public function renderCreateButton()
  536. {
  537. if (! $this->options['create_button']) {
  538. return '';
  539. }
  540. return (new Tools\CreateButton($this))->render();
  541. }
  542. /**
  543. * @param bool $value
  544. * @return $this
  545. */
  546. public function withBorder(bool $value = true)
  547. {
  548. $this->options['bordered'] = $value;
  549. return $this;
  550. }
  551. /**
  552. * @param bool $value
  553. * @return $this
  554. */
  555. public function tableCollapse(bool $value = true)
  556. {
  557. $this->options['table_collapse'] = $value;
  558. return $this;
  559. }
  560. /**
  561. * 显示横轴滚动条.
  562. *
  563. * @param bool $value
  564. * @return $this
  565. */
  566. public function scrollbar(bool $value = true)
  567. {
  568. $this->options['table_scrollbar'] = $value;
  569. return $this;
  570. }
  571. /**
  572. * Set grid header.
  573. *
  574. * @param Closure|string|Renderable $content
  575. * @return $this
  576. */
  577. public function header($content)
  578. {
  579. $this->header[] = $content;
  580. return $this;
  581. }
  582. /**
  583. * Render grid header.
  584. *
  585. * @return string
  586. */
  587. public function renderHeader()
  588. {
  589. if (! $this->header) {
  590. return '';
  591. }
  592. return <<<HTML
  593. <div class="card-header clearfix" style="border-bottom: 0;background: transparent;padding: 0">{$this->renderHeaderOrFooter($this->header)}</div>
  594. HTML;
  595. }
  596. protected function renderHeaderOrFooter($callbacks)
  597. {
  598. $target = [$this->processFilter(), $this];
  599. $content = [];
  600. foreach ($callbacks as $callback) {
  601. $content[] = Helper::render($callback, $target);
  602. }
  603. if (empty($content)) {
  604. return '';
  605. }
  606. return implode('<div class="mb-1 clearfix"></div>', $content);
  607. }
  608. /**
  609. * Set grid footer.
  610. *
  611. * @param Closure|string|Renderable $content
  612. * @return $this
  613. */
  614. public function footer($content)
  615. {
  616. $this->footer[] = $content;
  617. return $this;
  618. }
  619. /**
  620. * Render grid footer.
  621. *
  622. * @return string
  623. */
  624. public function renderFooter()
  625. {
  626. if (! $this->footer) {
  627. return '';
  628. }
  629. return <<<HTML
  630. <div class="box-footer clearfix">{$this->renderHeaderOrFooter($this->footer)}</div>
  631. HTML;
  632. }
  633. /**
  634. * Get or set option for grid.
  635. *
  636. * @param string|array $key
  637. * @param mixed $value
  638. * @return $this|mixed
  639. */
  640. public function option($key, $value = null)
  641. {
  642. if (is_null($value)) {
  643. return $this->options[$key] ?? null;
  644. }
  645. if (is_array($key)) {
  646. $this->options = array_merge($this->options, $key);
  647. } else {
  648. $this->options[$key] = $value;
  649. }
  650. return $this;
  651. }
  652. protected function setUpOptions()
  653. {
  654. if ($this->options['bordered']) {
  655. $this->tableCollapse(false);
  656. }
  657. }
  658. /**
  659. * Disable row selector.
  660. *
  661. * @return $this
  662. */
  663. public function disableRowSelector(bool $disable = true)
  664. {
  665. $this->tools->disableBatchActions($disable);
  666. return $this->option('row_selector', ! $disable);
  667. }
  668. /**
  669. * Show row selector.
  670. *
  671. * @return $this
  672. */
  673. public function showRowSelector(bool $val = true)
  674. {
  675. return $this->disableRowSelector(! $val);
  676. }
  677. /**
  678. * Remove create button on grid.
  679. *
  680. * @return $this
  681. */
  682. public function disableCreateButton(bool $disable = true)
  683. {
  684. return $this->option('create_button', ! $disable);
  685. }
  686. /**
  687. * Show create button.
  688. *
  689. * @return $this
  690. */
  691. public function showCreateButton(bool $val = true)
  692. {
  693. return $this->disableCreateButton(! $val);
  694. }
  695. /**
  696. * If allow creation.
  697. *
  698. * @return bool
  699. */
  700. public function allowCreateButton()
  701. {
  702. return $this->options['create_button'];
  703. }
  704. /**
  705. * @param string $mode
  706. * @return $this
  707. */
  708. public function createMode(string $mode)
  709. {
  710. return $this->option('create_mode', $mode);
  711. }
  712. /**
  713. * @return $this
  714. */
  715. public function enableDialogCreate()
  716. {
  717. return $this->createMode(self::CREATE_MODE_DIALOG);
  718. }
  719. /**
  720. * Get or set resource path.
  721. *
  722. * @return string
  723. */
  724. public function resource()
  725. {
  726. return $this->resourcePath;
  727. }
  728. /**
  729. * Create a grid instance.
  730. *
  731. * @param mixed ...$params
  732. * @return $this
  733. */
  734. public static function make(...$params)
  735. {
  736. return new static(...$params);
  737. }
  738. /**
  739. * @param Closure $closure
  740. * @return $this;
  741. */
  742. public function wrap(\Closure $closure)
  743. {
  744. $this->wrapper = $closure;
  745. return $this;
  746. }
  747. /**
  748. * @return bool
  749. */
  750. public function hasWrapper()
  751. {
  752. return $this->wrapper ? true : false;
  753. }
  754. /**
  755. * Add variables to grid view.
  756. *
  757. * @param array $variables
  758. * @return $this
  759. */
  760. public function with(array $variables)
  761. {
  762. return $this->addVariables($variables);
  763. }
  764. /**
  765. * Get all variables will used in grid view.
  766. *
  767. * @return array
  768. */
  769. protected function defaultVariables()
  770. {
  771. return [
  772. 'grid' => $this,
  773. 'tableId' => $this->getTableId(),
  774. ];
  775. }
  776. /**
  777. * Set a view to render.
  778. *
  779. * @param string $view
  780. * @return $this
  781. */
  782. public function view($view)
  783. {
  784. $this->view = $view;
  785. return $this;
  786. }
  787. /**
  788. * Set grid title.
  789. *
  790. * @param string $title
  791. * @return $this
  792. */
  793. public function title($title)
  794. {
  795. $this->variables['title'] = $title;
  796. return $this;
  797. }
  798. /**
  799. * Set grid description.
  800. *
  801. * @param string $description
  802. * @return $this
  803. */
  804. public function description($description)
  805. {
  806. $this->variables['description'] = $description;
  807. return $this;
  808. }
  809. /**
  810. * Set resource path for grid.
  811. *
  812. * @param string $path
  813. * @return $this
  814. */
  815. public function setResource($path)
  816. {
  817. $this->resourcePath = admin_url($path);
  818. return $this;
  819. }
  820. /**
  821. * 设置是否显示.
  822. *
  823. * @param bool $value
  824. * @return $this
  825. */
  826. public function show(bool $value = true)
  827. {
  828. $this->show = $value;
  829. return $this;
  830. }
  831. /**
  832. * 是否显示横向滚动条.
  833. *
  834. * @param bool $value
  835. * @return $this
  836. */
  837. public function scrollbarX(bool $value = true)
  838. {
  839. $this->options['scrollbar_x'] = $value;
  840. return $this;
  841. }
  842. /**
  843. * @return string
  844. */
  845. public function formatTableParentClass()
  846. {
  847. $tableCollaps = $this->option('table_collapse') ? 'table-collapse' : '';
  848. $scrollbarX = $this->option('scrollbar_x') ? 'table-scrollbar-x' : '';
  849. return "table-responsive table-wrapper complex-container table-middle mt-1 {$tableCollaps} {$scrollbarX}";
  850. }
  851. /**
  852. * Get the string contents of the grid view.
  853. *
  854. * @return string
  855. */
  856. public function render()
  857. {
  858. $this->callComposing();
  859. $this->build();
  860. $this->applyFixColumns();
  861. $this->setUpOptions();
  862. $this->addFilterScript();
  863. $this->addScript();
  864. return $this->doWrap();
  865. }
  866. public function getView()
  867. {
  868. if ($this->async && $this->hasFixColumns()) {
  869. return 'admin::grid.async-fixed-table';
  870. }
  871. return $this->view;
  872. }
  873. protected function addScript()
  874. {
  875. if ($this->async && ! $this->isAsyncRequest()) {
  876. $query = static::ASYNC_NAME;
  877. $url = Helper::fullUrlWithoutQuery(['_pjax']);
  878. $url = Helper::urlWithQuery($url, [static::ASYNC_NAME => 1]);
  879. $options = [
  880. 'selector' => ".async-{$this->getTableId()}",
  881. 'queryName' => $query,
  882. 'url' => $url,
  883. ];
  884. if ($this->hasFixColumns()) {
  885. $options['loadingStyle'] = 'height:140px;';
  886. }
  887. $options = json_encode($options);
  888. Admin::script(
  889. <<<JS
  890. Dcat.grid.async({$options}).render()
  891. JS
  892. );
  893. }
  894. }
  895. /**
  896. * @return string
  897. */
  898. protected function doWrap()
  899. {
  900. if (! $this->show) {
  901. return;
  902. }
  903. $view = view($this->getView(), $this->variables());
  904. if (! $wrapper = $this->wrapper) {
  905. return $view->render();
  906. }
  907. return Helper::render($wrapper($view));
  908. }
  909. /**
  910. * Add column to grid.
  911. *
  912. * @param string $name
  913. * @return Column
  914. */
  915. public function __get($name)
  916. {
  917. return $this->addColumn($name);
  918. }
  919. /**
  920. * Dynamically add columns to the grid view.
  921. *
  922. * @param $method
  923. * @param $arguments
  924. * @return Column
  925. */
  926. public function __call($method, $arguments)
  927. {
  928. if (static::hasMacro($method)) {
  929. return $this->macroCall($method, $arguments);
  930. }
  931. return $this->addColumn($method, $arguments[0] ?? null);
  932. }
  933. public function __toString()
  934. {
  935. return (string) $this->render();
  936. }
  937. }