Grid.php 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  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. * Set grid header.
  579. *
  580. * @param Closure|string|Renderable $content
  581. *
  582. * @return $this
  583. */
  584. public function header($content)
  585. {
  586. $this->header[] = $content;
  587. return $this;
  588. }
  589. /**
  590. * Render grid header.
  591. *
  592. * @return string
  593. */
  594. public function renderHeader()
  595. {
  596. if (! $this->header) {
  597. return '';
  598. }
  599. return <<<HTML
  600. <div class="card-header clearfix" style="border-bottom: 0;background: transparent;padding: 0">{$this->renderHeaderOrFooter($this->header)}</div>
  601. HTML;
  602. }
  603. protected function renderHeaderOrFooter($callbacks)
  604. {
  605. $target = [$this->processFilter()];
  606. $content = [];
  607. foreach ($callbacks as $callback) {
  608. $content[] = Helper::render($callback, $target);
  609. }
  610. if (empty($content)) {
  611. return '';
  612. }
  613. return implode('<div class="mb-1 clearfix"></div>', $content);
  614. }
  615. /**
  616. * Set grid footer.
  617. *
  618. * @param Closure|string|Renderable $content
  619. *
  620. * @return $this
  621. */
  622. public function footer($content)
  623. {
  624. $this->footer[] = $content;
  625. return $this;
  626. }
  627. /**
  628. * Render grid footer.
  629. *
  630. * @return string
  631. */
  632. public function renderFooter()
  633. {
  634. if (! $this->footer) {
  635. return '';
  636. }
  637. return <<<HTML
  638. <div class="box-footer clearfix">{$this->renderHeaderOrFooter($this->footer)}</div>
  639. HTML;
  640. }
  641. /**
  642. * Get or set option for grid.
  643. *
  644. * @param string|array $key
  645. * @param mixed $value
  646. *
  647. * @return $this|mixed
  648. */
  649. public function option($key, $value = null)
  650. {
  651. if (is_null($value)) {
  652. return $this->options[$key] ?? null;
  653. }
  654. if (is_array($key)) {
  655. $this->options = array_merge($this->options, $key);
  656. } else {
  657. $this->options[$key] = $value;
  658. }
  659. return $this;
  660. }
  661. protected function setUpOptions()
  662. {
  663. if ($this->options['bordered']) {
  664. $this->tableCollapse(false);
  665. }
  666. }
  667. /**
  668. * Disable row selector.
  669. *
  670. * @return $this
  671. */
  672. public function disableRowSelector(bool $disable = true)
  673. {
  674. $this->tools->disableBatchActions($disable);
  675. return $this->option('row_selector', ! $disable);
  676. }
  677. /**
  678. * Show row selector.
  679. *
  680. * @return $this
  681. */
  682. public function showRowSelector(bool $val = true)
  683. {
  684. return $this->disableRowSelector(! $val);
  685. }
  686. /**
  687. * Remove create button on grid.
  688. *
  689. * @return $this
  690. */
  691. public function disableCreateButton(bool $disable = true)
  692. {
  693. return $this->option('create_button', ! $disable);
  694. }
  695. /**
  696. * Show create button.
  697. *
  698. * @return $this
  699. */
  700. public function showCreateButton(bool $val = true)
  701. {
  702. return $this->disableCreateButton(! $val);
  703. }
  704. /**
  705. * If allow creation.
  706. *
  707. * @return bool
  708. */
  709. public function allowCreateButton()
  710. {
  711. return $this->options['create_button'];
  712. }
  713. /**
  714. * @param string $mode
  715. *
  716. * @return $this
  717. */
  718. public function createMode(string $mode)
  719. {
  720. return $this->option('create_mode', $mode);
  721. }
  722. /**
  723. * @return $this
  724. */
  725. public function enableDialogCreate()
  726. {
  727. return $this->createMode(self::CREATE_MODE_DIALOG);
  728. }
  729. /**
  730. * Get or set resource path.
  731. *
  732. * @return string
  733. */
  734. public function resource()
  735. {
  736. return $this->resourcePath;
  737. }
  738. /**
  739. * Create a grid instance.
  740. *
  741. * @param mixed ...$params
  742. *
  743. * @return $this
  744. */
  745. public static function make(...$params)
  746. {
  747. return new static(...$params);
  748. }
  749. /**
  750. * @param Closure $closure
  751. *
  752. * @return $this;
  753. */
  754. public function wrap(\Closure $closure)
  755. {
  756. $this->wrapper = $closure;
  757. return $this;
  758. }
  759. /**
  760. * @return bool
  761. */
  762. public function hasWrapper()
  763. {
  764. return $this->wrapper ? true : false;
  765. }
  766. /**
  767. * Add variables to grid view.
  768. *
  769. * @param array $variables
  770. *
  771. * @return $this
  772. */
  773. public function with(array $variables)
  774. {
  775. return $this->addVariables($variables);
  776. }
  777. /**
  778. * Get all variables will used in grid view.
  779. *
  780. * @return array
  781. */
  782. protected function defaultVariables()
  783. {
  784. return [
  785. 'grid' => $this,
  786. 'tableId' => $this->getTableId(),
  787. ];
  788. }
  789. /**
  790. * Set a view to render.
  791. *
  792. * @param string $view
  793. *
  794. * @return $this
  795. */
  796. public function view($view)
  797. {
  798. $this->view = $view;
  799. return $this;
  800. }
  801. /**
  802. * Set grid title.
  803. *
  804. * @param string $title
  805. *
  806. * @return $this
  807. */
  808. public function title($title)
  809. {
  810. $this->variables['title'] = $title;
  811. return $this;
  812. }
  813. /**
  814. * Set grid description.
  815. *
  816. * @param string $description
  817. *
  818. * @return $this
  819. */
  820. public function description($description)
  821. {
  822. $this->variables['description'] = $description;
  823. return $this;
  824. }
  825. /**
  826. * Set resource path for grid.
  827. *
  828. * @param string $path
  829. *
  830. * @return $this
  831. */
  832. public function setResource($path)
  833. {
  834. $this->resourcePath = admin_url($path);
  835. return $this;
  836. }
  837. /**
  838. * 设置是否显示.
  839. *
  840. * @param bool $value
  841. *
  842. * @return $this
  843. */
  844. public function show(bool $value = true)
  845. {
  846. $this->show = $value;
  847. return $this;
  848. }
  849. /**
  850. * 是否显示横向滚动条.
  851. *
  852. * @param bool $value
  853. *
  854. * @return $this
  855. */
  856. public function scrollbarX(bool $value = true)
  857. {
  858. $this->options['scrollbar_x'] = $value;
  859. return $this;
  860. }
  861. /**
  862. * @return string
  863. */
  864. public function formatTableParentClass()
  865. {
  866. $tableCollaps = $this->option('table_collapse') ? 'table-collapse' : '';
  867. $scrollbarX = $this->option('scrollbar_x') ? 'table-scrollbar-x' : '';
  868. return "table-responsive table-wrapper complex-container table-middle mt-1 {$tableCollaps} {$scrollbarX}";
  869. }
  870. /**
  871. * Get the string contents of the grid view.
  872. *
  873. * @return string
  874. */
  875. public function render()
  876. {
  877. $this->callComposing();
  878. $this->build();
  879. $this->applyFixColumns();
  880. $this->setUpOptions();
  881. $this->addFilterScript();
  882. $this->addScript();
  883. return $this->doWrap();
  884. }
  885. public function getView()
  886. {
  887. if ($this->async && $this->hasFixColumns()) {
  888. return 'admin::grid.async-fixed-table';
  889. }
  890. return $this->view;
  891. }
  892. protected function addScript()
  893. {
  894. if ($this->async && ! $this->isAsyncRequest()) {
  895. $query = static::ASYNC_NAME;
  896. $url = Helper::fullUrlWithoutQuery(['_pjax']);
  897. $url = Helper::urlWithQuery($url, [static::ASYNC_NAME => 1]);
  898. $options = [
  899. 'selector' => ".async-{$this->getTableId()}",
  900. 'queryName' => $query,
  901. 'url' => $url,
  902. ];
  903. if ($this->hasFixColumns()) {
  904. $options['loadingStyle'] = 'height:140px;';
  905. }
  906. $options = json_encode($options);
  907. Admin::script(
  908. <<<JS
  909. Dcat.grid.async({$options}).render()
  910. JS
  911. );
  912. }
  913. }
  914. /**
  915. * @return string
  916. */
  917. protected function doWrap()
  918. {
  919. if (! $this->show) {
  920. return;
  921. }
  922. $view = view($this->getView(), $this->variables());
  923. if (! $wrapper = $this->wrapper) {
  924. return $view->render();
  925. }
  926. return Helper::render($wrapper($view));
  927. }
  928. /**
  929. * Add column to grid.
  930. *
  931. * @param string $name
  932. *
  933. * @return Column
  934. */
  935. public function __get($name)
  936. {
  937. return $this->addColumn($name);
  938. }
  939. /**
  940. * Dynamically add columns to the grid view.
  941. *
  942. * @param $method
  943. * @param $arguments
  944. *
  945. * @return Column
  946. */
  947. public function __call($method, $arguments)
  948. {
  949. if (static::hasMacro($method)) {
  950. return $this->macroCall($method, $arguments);
  951. }
  952. return $this->addColumn($method, $arguments[0] ?? null);
  953. }
  954. public function __toString()
  955. {
  956. return (string) $this->render();
  957. }
  958. }