Field.php 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. <?php
  2. namespace Dcat\Admin\Form;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Form;
  5. use Dcat\Admin\Support\Helper;
  6. use Dcat\Admin\Traits\HasBuilderEvents;
  7. use Dcat\Admin\Traits\HasVariables;
  8. use Dcat\Admin\Widgets\Form as WidgetForm;
  9. use Illuminate\Contracts\Support\Arrayable;
  10. use Illuminate\Contracts\Support\Renderable;
  11. use Illuminate\Support\Arr;
  12. use Illuminate\Support\Fluent;
  13. use Illuminate\Support\Traits\Macroable;
  14. /**
  15. * Class Field.
  16. */
  17. class Field implements Renderable
  18. {
  19. use Macroable;
  20. use Form\Concerns\HasFieldValidator;
  21. use HasBuilderEvents;
  22. use HasVariables;
  23. const FILE_DELETE_FLAG = '_file_del_';
  24. const FIELD_CLASS_PREFIX = 'field_';
  25. const BUILD_IGNORE = 'build-ignore';
  26. const NORMAL_CLASS = '_normal_';
  27. /**
  28. * Element value.
  29. *
  30. * @var mixed
  31. */
  32. protected $value;
  33. /**
  34. * Data of all original columns of value.
  35. *
  36. * @var mixed
  37. */
  38. protected $data;
  39. /**
  40. * Field original value.
  41. *
  42. * @var mixed
  43. */
  44. protected $original;
  45. /**
  46. * Field default value.
  47. *
  48. * @var mixed
  49. */
  50. protected $default;
  51. /**
  52. * @var bool
  53. */
  54. protected $allowDefaultValueInEditPage = false;
  55. /**
  56. * Element label.
  57. *
  58. * @var string
  59. */
  60. protected $label = '';
  61. /**
  62. * Column name.
  63. *
  64. * @var string|array
  65. */
  66. protected $column = '';
  67. /**
  68. * Form element name.
  69. *
  70. * @var string|array
  71. */
  72. protected $elementName = [];
  73. /**
  74. * Form element classes.
  75. *
  76. * @var array
  77. */
  78. protected $elementClass = [];
  79. /**
  80. * Options for specify elements.
  81. *
  82. * @var array
  83. */
  84. protected $options = [];
  85. /**
  86. * Checked for specify elements.
  87. *
  88. * @var array
  89. */
  90. protected $checked = [];
  91. /**
  92. * Css required by this field.
  93. *
  94. * @var array
  95. */
  96. protected static $css = [];
  97. /**
  98. * Js required by this field.
  99. *
  100. * @var array
  101. */
  102. protected static $js = [];
  103. /**
  104. * Script for field.
  105. *
  106. * @var string
  107. */
  108. protected $script = '';
  109. /**
  110. * Element attributes.
  111. *
  112. * @var array
  113. */
  114. protected $attributes = [];
  115. /**
  116. * Parent form.
  117. *
  118. * @var Form|WidgetForm
  119. */
  120. protected $form;
  121. /**
  122. * @var WidgetForm
  123. */
  124. protected $parent;
  125. /**
  126. * View for field to render.
  127. *
  128. * @var string
  129. */
  130. protected $view = '';
  131. /**
  132. * Help block.
  133. *
  134. * @var array
  135. */
  136. protected $help = [];
  137. /**
  138. * Key for errors.
  139. *
  140. * @var string|array
  141. */
  142. protected $errorKey;
  143. /**
  144. * Placeholder for this field.
  145. *
  146. * @var string|array
  147. */
  148. protected $placeholder;
  149. /**
  150. * Width for label and field.
  151. *
  152. * @var array
  153. */
  154. protected $width = [
  155. 'label' => 2,
  156. 'field' => 8,
  157. ];
  158. /**
  159. * If the form horizontal layout.
  160. *
  161. * @var bool
  162. */
  163. protected $horizontal = true;
  164. /**
  165. * column data format.
  166. *
  167. * @var \Closure
  168. */
  169. protected $customFormat = null;
  170. /**
  171. * @var bool
  172. */
  173. protected $display = true;
  174. /**
  175. * @var array
  176. */
  177. protected $labelClass = ['text-capitalize'];
  178. /**
  179. * @var array
  180. */
  181. protected $fieldClass = [];
  182. /**
  183. * @var array
  184. */
  185. protected $formGroupClass = ['form-field'];
  186. /**
  187. * @var \Closure[]
  188. */
  189. protected $savingCallbacks = [];
  190. /**
  191. * Field constructor.
  192. *
  193. * @param string|array $column
  194. * @param array $arguments
  195. */
  196. public function __construct($column, $arguments = [])
  197. {
  198. $this->column = $column;
  199. $this->label = $this->formatLabel($arguments);
  200. $this->callResolving();
  201. }
  202. /**
  203. * @param array $options
  204. *
  205. * @return $this
  206. */
  207. public function setRelation(array $options = [])
  208. {
  209. return $this;
  210. }
  211. /**
  212. * Format the label value.
  213. *
  214. * @param array $arguments
  215. *
  216. * @return string
  217. */
  218. protected function formatLabel($arguments = [])
  219. {
  220. if (isset($arguments[0])) {
  221. return $arguments[0];
  222. }
  223. $column = is_array($this->column) ? current($this->column) : $this->column;
  224. return str_replace('_', ' ', admin_trans_field($column));
  225. }
  226. /**
  227. * Format the name of the field.
  228. *
  229. * @param string $column
  230. *
  231. * @return array|mixed|string
  232. */
  233. protected function formatName($column)
  234. {
  235. return Helper::formatElementName($column);
  236. }
  237. /**
  238. * Set form element name.
  239. *
  240. * @param string|array $name
  241. *
  242. * @return $this
  243. *
  244. * @author Edwin Hui
  245. */
  246. public function setElementName($name)
  247. {
  248. $this->elementName = $name;
  249. return $this;
  250. }
  251. /**
  252. * Get form element name.
  253. *
  254. * @return array|mixed|string
  255. */
  256. public function getElementName()
  257. {
  258. return $this->elementName ?: $this->formatName($this->column);
  259. }
  260. /**
  261. * Fill data to the field.
  262. *
  263. * @param array $data
  264. *
  265. * @return void
  266. */
  267. final public function fill($data)
  268. {
  269. $data = Helper::array($data);
  270. $this->data($data);
  271. $this->value = $this->formatFieldData($data);
  272. $this->callCustomFormatter();
  273. }
  274. /**
  275. * Format field data.
  276. *
  277. * @param array $data
  278. *
  279. * @return mixed
  280. */
  281. protected function formatFieldData($data)
  282. {
  283. if (is_array($this->column)) {
  284. $value = [];
  285. foreach ($this->column as $key => $column) {
  286. $value[$key] = Arr::get($data, $this->normalizeColumn($column));
  287. }
  288. return $value;
  289. }
  290. return Arr::get($data, $this->normalizeColumn(), $this->value);
  291. }
  292. protected function normalizeColumn(?string $column = null)
  293. {
  294. return str_replace('->', '.', $column ?: $this->column);
  295. }
  296. /**
  297. * custom format form column data when edit.
  298. *
  299. * @param \Closure $call
  300. *
  301. * @return $this
  302. */
  303. public function customFormat(\Closure $call)
  304. {
  305. $this->customFormat = $call;
  306. return $this;
  307. }
  308. /**
  309. * Set original value to the field.
  310. *
  311. * @param array $data
  312. *
  313. * @return void
  314. */
  315. final public function setOriginal($data)
  316. {
  317. $data = Helper::array($data);
  318. $this->original = $this->formatFieldData($data);
  319. $this->callCustomFormatter('original', new Fluent($data));
  320. }
  321. /**
  322. * @param string $key
  323. * @param Fluent|null $dataremoveField
  324. */
  325. protected function callCustomFormatter($key = 'value', Fluent $data = null)
  326. {
  327. if ($this->customFormat) {
  328. $this->{$key} = $this->customFormat
  329. ->call(
  330. $data ?: $this->data(),
  331. $this->{$key},
  332. $this->column,
  333. $this
  334. );
  335. }
  336. }
  337. /**
  338. * @param Form|WidgetForm $form
  339. *
  340. * @return $this
  341. */
  342. public function setForm($form = null)
  343. {
  344. $this->form = $form;
  345. return $this;
  346. }
  347. /**
  348. * @param WidgetForm $form
  349. *
  350. * @return $this
  351. */
  352. public function setParent($form = null)
  353. {
  354. $this->parent = $form;
  355. return $this;
  356. }
  357. /**
  358. * @return Fluent
  359. */
  360. public function values()
  361. {
  362. return $this->form ? $this->form->model() : new Fluent();
  363. }
  364. /**
  365. * Set width for field and label.
  366. *
  367. * @param int $field
  368. * @param int $label
  369. *
  370. * @return $this
  371. */
  372. public function width($field = 8, $label = 2)
  373. {
  374. $this->width = [
  375. 'label' => $label,
  376. 'field' => $field,
  377. ];
  378. return $this;
  379. }
  380. /**
  381. * Set the field options.
  382. *
  383. * @param array $options
  384. *
  385. * @return $this
  386. */
  387. public function options($options = [])
  388. {
  389. if ($options instanceof \Closure) {
  390. $options = $options->call($this->data(), $this->value());
  391. }
  392. $this->options = array_merge($this->options, Helper::array($options));
  393. return $this;
  394. }
  395. /**
  396. * @param array $options
  397. *
  398. * @return $this
  399. */
  400. public function replaceOptions($options)
  401. {
  402. if ($options instanceof \Closure) {
  403. $options = $options->call($this->data(), $this->value());
  404. }
  405. $this->options = $options;
  406. return $this;
  407. }
  408. /**
  409. * @param array|Arrayable $options
  410. *
  411. * @return $this
  412. */
  413. public function mergeOptions($options)
  414. {
  415. return $this->options($options);
  416. }
  417. /**
  418. * Set the field option checked.
  419. *
  420. * @param array $checked
  421. *
  422. * @return $this
  423. */
  424. public function checked($checked = [])
  425. {
  426. if ($checked instanceof Arrayable) {
  427. $checked = $checked->toArray();
  428. }
  429. $this->checked = array_merge($this->checked, (array) $checked);
  430. return $this;
  431. }
  432. /**
  433. * Set key for error message.
  434. *
  435. * @param string|array $key
  436. *
  437. * @return $this
  438. */
  439. public function setErrorKey($key)
  440. {
  441. $this->errorKey = $key;
  442. return $this;
  443. }
  444. /**
  445. * Get key for error message.
  446. *
  447. * @return string
  448. */
  449. public function getErrorKey()
  450. {
  451. return $this->errorKey ?: $this->column;
  452. }
  453. /**
  454. * Set or get value of the field.
  455. *
  456. * @param null $value
  457. *
  458. * @return mixed
  459. */
  460. public function value($value = null)
  461. {
  462. if (is_null($value)) {
  463. if (
  464. $this->value === null
  465. || (is_array($this->value) && empty($this->value))
  466. ) {
  467. return $this->default();
  468. }
  469. return $this->value;
  470. }
  471. $this->value = value($value);
  472. return $this;
  473. }
  474. /**
  475. * Set or get data.
  476. *
  477. * @param array $data
  478. *
  479. * @return $this|Fluent
  480. */
  481. public function data(array $data = null)
  482. {
  483. if (is_null($data)) {
  484. if (! $this->data || is_array($this->data)) {
  485. $this->data = new Fluent((array) $this->data);
  486. }
  487. return $this->data;
  488. }
  489. $this->data = new Fluent($data);
  490. return $this;
  491. }
  492. /**
  493. * Get or set default value for field.
  494. *
  495. * @param mixed $default
  496. * @param bool $edit
  497. *
  498. * @return $this|mixed
  499. */
  500. public function default($default = null, bool $edit = false)
  501. {
  502. if ($default === null) {
  503. if (
  504. $this->form
  505. && method_exists($this->form, 'isCreating')
  506. && ! $this->form->isCreating()
  507. && ! $this->allowDefaultValueInEditPage
  508. ) {
  509. return;
  510. }
  511. if ($this->default instanceof \Closure) {
  512. $this->default->bindTo($this->data());
  513. return call_user_func($this->default, $this->form);
  514. }
  515. return $this->default;
  516. }
  517. $this->default = value($default);
  518. $this->allowDefaultValueInEditPage = $edit;
  519. return $this;
  520. }
  521. /**
  522. * Set help block for current field.
  523. *
  524. * @param string $text
  525. * @param string $icon
  526. *
  527. * @return $this
  528. */
  529. public function help($text = '', $icon = 'feather icon-help-circle')
  530. {
  531. $this->help = compact('text', 'icon');
  532. return $this;
  533. }
  534. /**
  535. * Get column of the field.
  536. *
  537. * @return string|array
  538. */
  539. public function column()
  540. {
  541. return $this->column;
  542. }
  543. /**
  544. * Get or set label of the field.
  545. *
  546. * @param null $label
  547. *
  548. * @return $this|string
  549. */
  550. public function label($label = null)
  551. {
  552. if ($label == null) {
  553. return $this->label;
  554. }
  555. if ($label instanceof \Closure) {
  556. $label = $label($this->label);
  557. }
  558. $this->label = $label;
  559. return $this;
  560. }
  561. /**
  562. * Get original value of the field.
  563. *
  564. * @return mixed
  565. */
  566. public function original()
  567. {
  568. return $this->original;
  569. }
  570. /**
  571. * Sanitize input data.
  572. *
  573. * @param array $input
  574. * @param string $column
  575. *
  576. * @return array
  577. */
  578. protected function sanitizeInput($input, $column)
  579. {
  580. if ($this instanceof Field\MultipleSelect) {
  581. $value = Arr::get($input, $column);
  582. Arr::set($input, $column, array_filter($value));
  583. }
  584. return $input;
  585. }
  586. /**
  587. * Add html attributes to elements.
  588. *
  589. * @param array|string $attribute
  590. * @param mixed $value
  591. *
  592. * @return $this
  593. */
  594. public function attribute($attribute, $value = null)
  595. {
  596. if (is_array($attribute)) {
  597. $this->attributes = array_merge($this->attributes, $attribute);
  598. } else {
  599. $this->attributes[$attribute] = (string) $value;
  600. }
  601. return $this;
  602. }
  603. /**
  604. * @param string $key
  605. *
  606. * @return bool
  607. */
  608. public function hasAttribute(string $key)
  609. {
  610. return array_key_exists($key, $this->attributes);
  611. }
  612. /**
  613. * @param string $key
  614. *
  615. * @return mixed|null
  616. */
  617. public function getAttribute(string $key)
  618. {
  619. return $this->attributes[$key] ?? null;
  620. }
  621. /**
  622. * Specifies a regular expression against which to validate the value of the input.
  623. *
  624. * @param string $error
  625. * @param string $regexp
  626. *
  627. * @return $this
  628. */
  629. public function pattern($regexp, $error = null)
  630. {
  631. if ($error) {
  632. $this->attribute('data-pattern-error', $error);
  633. }
  634. return $this->attribute('pattern', $regexp);
  635. }
  636. /**
  637. * set the input filed required.
  638. *
  639. * @param bool $isLabelAsterisked
  640. *
  641. * @return $this
  642. */
  643. public function required($isLabelAsterisked = true)
  644. {
  645. if ($isLabelAsterisked) {
  646. $this->setLabelClass(['asterisk']);
  647. }
  648. $this->rules('required');
  649. return $this->attribute('required', true);
  650. }
  651. /**
  652. * Set the field automatically get focus.
  653. *
  654. * @param bool $value
  655. *
  656. * @return $this
  657. */
  658. public function autofocus(bool $value = true)
  659. {
  660. return $this->attribute('autofocus', $value);
  661. }
  662. /**
  663. * Set the field as readonly mode.
  664. *
  665. * @param bool $value
  666. *
  667. * @return $this
  668. */
  669. public function readOnly(bool $value = true)
  670. {
  671. return $this->attribute('readonly', $value);
  672. }
  673. /**
  674. * Set field as disabled.
  675. *
  676. * @param bool $value
  677. *
  678. * @return $this
  679. */
  680. public function disable(bool $value = true)
  681. {
  682. return $this->attribute('disabled', $value);
  683. }
  684. /**
  685. * Get or set field placeholder.
  686. *
  687. * @param string $placeholder
  688. *
  689. * @return $this|string
  690. */
  691. public function placeholder($placeholder = null)
  692. {
  693. if ($placeholder === null) {
  694. return $this->placeholder ?: trans('admin.input').' '.$this->label;
  695. }
  696. $this->placeholder = $placeholder;
  697. return $this;
  698. }
  699. /**
  700. * @param mixed $value
  701. *
  702. * @return mixed
  703. */
  704. protected function prepareInputValue($value)
  705. {
  706. return $value;
  707. }
  708. /**
  709. * @param \Closure $closure
  710. *
  711. * @return $this
  712. */
  713. public function saving(\Closure $closure)
  714. {
  715. $this->savingCallbacks[] = $closure;
  716. return $this;
  717. }
  718. /**
  719. * Prepare for a field value before update or insert.
  720. *
  721. * @param mixed $value
  722. *
  723. * @return mixed
  724. */
  725. final public function prepare($value)
  726. {
  727. $value = $this->prepareInputValue($value);
  728. if ($this->savingCallbacks) {
  729. foreach ($this->savingCallbacks as $callback) {
  730. $value = $callback->call($this->data(), $value);
  731. }
  732. }
  733. return $value;
  734. }
  735. /**
  736. * Format the field attributes.
  737. *
  738. * @return string
  739. */
  740. protected function formatAttributes()
  741. {
  742. $html = [];
  743. foreach ($this->attributes as $name => $value) {
  744. $html[] = $name.'="'.e($value).'"';
  745. }
  746. return implode(' ', $html);
  747. }
  748. /**
  749. * @param bool $value
  750. *
  751. * @return $this
  752. */
  753. public function horizontal(bool $value = true)
  754. {
  755. $this->horizontal = $value;
  756. return $this;
  757. }
  758. /**
  759. * @return array
  760. */
  761. public function getViewElementClasses()
  762. {
  763. if ($this->horizontal) {
  764. return [
  765. 'label' => "col-md-{$this->width['label']} {$this->getLabelClass()}",
  766. 'field' => "col-md-{$this->width['field']} {$this->getFieldClass()}",
  767. 'form-group' => "form-group row {$this->getFormGroupClass()}",
  768. ];
  769. }
  770. return [
  771. 'label' => $this->getLabelClass(),
  772. 'field' => $this->getFieldClass(),
  773. 'form-group' => $this->getFormGroupClass(),
  774. ];
  775. }
  776. /**
  777. * Set element class.
  778. *
  779. * @param string|array $class
  780. *
  781. * @return $this
  782. */
  783. public function setElementClass($class)
  784. {
  785. $this->elementClass = array_merge($this->elementClass, (array) $this->normalizeElementClass($class));
  786. return $this;
  787. }
  788. /**
  789. * Get element class.
  790. *
  791. * @return array
  792. */
  793. public function getElementClass()
  794. {
  795. if (! $this->elementClass) {
  796. $this->elementClass = $this->getDefaultElementClass();
  797. }
  798. return $this->elementClass;
  799. }
  800. /**
  801. * @return array
  802. */
  803. protected function getDefaultElementClass()
  804. {
  805. return array_merge($this->normalizeElementClass((array) $this->getElementName()), [static::NORMAL_CLASS]);
  806. }
  807. /**
  808. * @param string|array $class
  809. *
  810. * @return array|string
  811. */
  812. public function normalizeElementClass($class)
  813. {
  814. if (is_array($class)) {
  815. return array_map([$this, 'normalizeElementClass'], $class);
  816. }
  817. return static::FIELD_CLASS_PREFIX.str_replace(['[', ']', '->', '.'], '_', $class);
  818. }
  819. /**
  820. * Get element class selector.
  821. *
  822. * @return string|array
  823. */
  824. public function getElementClassSelector()
  825. {
  826. $elementClass = $this->getElementClass();
  827. $formId = $this->getFormElementId();
  828. $formId = $formId ? '#'.$formId : '';
  829. if (Arr::isAssoc($elementClass)) {
  830. $classes = [];
  831. foreach ($elementClass as $index => $class) {
  832. $classes[$index] = $formId.' .'.(is_array($class) ? implode('.', $class) : $class);
  833. }
  834. return $classes;
  835. }
  836. return $formId.' .'.implode('.', $elementClass);
  837. }
  838. /**
  839. * Get element class string.
  840. *
  841. * @return mixed
  842. */
  843. public function getElementClassString()
  844. {
  845. $elementClass = $this->getElementClass();
  846. if (Arr::isAssoc($elementClass)) {
  847. $classes = [];
  848. foreach ($elementClass as $index => $class) {
  849. $classes[$index] = is_array($class) ? implode(' ', $class) : $class;
  850. }
  851. return $classes;
  852. }
  853. return implode(' ', $elementClass);
  854. }
  855. /**
  856. * @return $this
  857. */
  858. public function hideInDialog()
  859. {
  860. if (
  861. $this->form instanceof Form
  862. && $this->form->inDialog()
  863. ) {
  864. $this->display(false);
  865. }
  866. return $this;
  867. }
  868. /**
  869. * @return string|null
  870. */
  871. protected function getFormElementId()
  872. {
  873. return $this->form ? $this->form->getElementId() : null;
  874. }
  875. /**
  876. * Add the element class.
  877. *
  878. * @param $class
  879. *
  880. * @return $this
  881. */
  882. public function addElementClass($class)
  883. {
  884. $this->elementClass = array_unique(
  885. array_merge($this->elementClass, (array) $class)
  886. );
  887. return $this;
  888. }
  889. /**
  890. * Remove element class.
  891. *
  892. * @param $class
  893. *
  894. * @return $this
  895. */
  896. public function removeElementClass($class)
  897. {
  898. Helper::deleteByValue($this->elementClass, $class);
  899. return $this;
  900. }
  901. /**
  902. * @param array|string $labelClass
  903. * @param bool $append
  904. *
  905. * @return $this|string
  906. */
  907. public function setLabelClass($labelClass, bool $append = true)
  908. {
  909. $this->labelClass = $append
  910. ? array_unique(array_merge($this->labelClass, (array) $labelClass))
  911. : (array) $labelClass;
  912. return $this;
  913. }
  914. /**
  915. * @return string
  916. */
  917. public function getLabelClass()
  918. {
  919. return implode(' ', $this->labelClass);
  920. }
  921. /**
  922. * @param mixed $value
  923. * @param callable $callback
  924. *
  925. * @return $this|mixed
  926. */
  927. public function when($value, $callback)
  928. {
  929. if ($value) {
  930. return $callback($this, $value) ?: $this;
  931. }
  932. return $this;
  933. }
  934. /**
  935. * @param string|array $class
  936. * @param bool $append
  937. *
  938. * @return $this
  939. */
  940. public function setFormGroupClass($class, bool $append = true)
  941. {
  942. $this->formGroupClass = $append
  943. ? array_unique(array_merge($this->formGroupClass, (array) $class))
  944. : (array) $class;
  945. return $this;
  946. }
  947. /**
  948. * @return string
  949. */
  950. public function getFormGroupClass()
  951. {
  952. return implode(' ', $this->formGroupClass);
  953. }
  954. /**
  955. * @param string|array $class
  956. * @param bool $append
  957. *
  958. * @return $this
  959. */
  960. public function setFieldClass($class, bool $append = true)
  961. {
  962. $this->fieldClass = $append
  963. ? array_unique(array_merge($this->fieldClass, (array) $class))
  964. : (array) $class;
  965. return $this;
  966. }
  967. public function getFieldClass()
  968. {
  969. return implode(' ', $this->fieldClass);
  970. }
  971. /**
  972. * Get the view variables of this field.
  973. *
  974. * @return array
  975. */
  976. public function defaultVariables()
  977. {
  978. return [
  979. 'name' => $this->getElementName(),
  980. 'help' => $this->help,
  981. 'class' => $this->getElementClassString(),
  982. 'value' => $this->value(),
  983. 'label' => $this->label,
  984. 'viewClass' => $this->getViewElementClasses(),
  985. 'column' => $this->column,
  986. 'errorKey' => $this->getErrorKey(),
  987. 'attributes' => $this->formatAttributes(),
  988. 'placeholder' => $this->placeholder(),
  989. 'disabled' => $this->attributes['disabled'] ?? false,
  990. 'formId' => $this->getFormElementId(),
  991. 'selector' => $this->getElementClassSelector(),
  992. 'options' => $this->options,
  993. ];
  994. }
  995. protected function isCreating()
  996. {
  997. return request()->isMethod('POST');
  998. }
  999. protected function isEditing()
  1000. {
  1001. return request()->isMethod('PUT');
  1002. }
  1003. /**
  1004. * Get view of this field.
  1005. *
  1006. * @return string
  1007. */
  1008. public function view()
  1009. {
  1010. return $this->view ?: 'admin::form.'.strtolower(class_basename(static::class));
  1011. }
  1012. /**
  1013. * Set view of current field.
  1014. *
  1015. * @return string
  1016. */
  1017. public function setView($view)
  1018. {
  1019. $this->view = $view;
  1020. return $this;
  1021. }
  1022. /**
  1023. * Get script of current field.
  1024. *
  1025. * @return string
  1026. */
  1027. public function getScript()
  1028. {
  1029. return $this->script;
  1030. }
  1031. /**
  1032. * Set script of current field.
  1033. *
  1034. * @return self
  1035. */
  1036. public function script($script)
  1037. {
  1038. $this->script = $script;
  1039. return $this;
  1040. }
  1041. /**
  1042. * To set this field should render or not.
  1043. *
  1044. * @return self
  1045. */
  1046. public function display(bool $display)
  1047. {
  1048. $this->display = $display;
  1049. return $this;
  1050. }
  1051. /**
  1052. * 设置默认属性.
  1053. *
  1054. * @param string $attribute
  1055. * @param mixed $value
  1056. *
  1057. * @return $this
  1058. */
  1059. public function defaultAttribute(string $attribute, $value)
  1060. {
  1061. if (! array_key_exists($attribute, $this->attributes)) {
  1062. $this->attribute($attribute, $value);
  1063. }
  1064. return $this;
  1065. }
  1066. /**
  1067. * If this field should render.
  1068. *
  1069. * @return bool
  1070. */
  1071. protected function shouldRender()
  1072. {
  1073. return $this->display;
  1074. }
  1075. /**
  1076. * 保存数据为json格式.
  1077. *
  1078. * @param int $option
  1079. *
  1080. * @return $this
  1081. */
  1082. public function saveAsJson($option = 0)
  1083. {
  1084. return $this->saving(function ($value) use ($option) {
  1085. if ($value === null || is_scalar($value)) {
  1086. return $value;
  1087. }
  1088. return json_encode($value, $option);
  1089. });
  1090. }
  1091. /**
  1092. * 保存数据为字符串格式.
  1093. *
  1094. * @return $this
  1095. */
  1096. public function saveAsString()
  1097. {
  1098. return $this->saving(function ($value) {
  1099. if (is_object($value) || is_array($value)) {
  1100. return json_encode($value);
  1101. }
  1102. return (string) $value;
  1103. });
  1104. }
  1105. /**
  1106. * Collect assets required by this field.
  1107. */
  1108. public static function requireAssets()
  1109. {
  1110. static::$js && Admin::js(static::$js);
  1111. static::$css && Admin::css(static::$css);
  1112. }
  1113. /**
  1114. * 设置默认class.
  1115. */
  1116. protected function setDefaultClass()
  1117. {
  1118. if (is_string($class = $this->getElementClassString())) {
  1119. $this->defaultAttribute('class', $class);
  1120. }
  1121. }
  1122. /**
  1123. * Render this filed.
  1124. *
  1125. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string
  1126. */
  1127. public function render()
  1128. {
  1129. if (! $this->shouldRender()) {
  1130. return '';
  1131. }
  1132. $this->setDefaultClass();
  1133. $this->callComposing();
  1134. $this->withScript();
  1135. return Admin::view($this->view(), $this->variables());
  1136. }
  1137. protected function withScript()
  1138. {
  1139. if ($this->script) {
  1140. Admin::script($this->script);
  1141. }
  1142. }
  1143. /**
  1144. * @return string
  1145. */
  1146. public function __toString()
  1147. {
  1148. $view = $this->render();
  1149. return $view instanceof Renderable ? $view->render() : (string) $view;
  1150. }
  1151. }