Field.php 25 KB

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