1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace Atk4\Ui\Form\Layout\Section;
6:
7: use Atk4\Ui\Accordion as UiAccordion;
8: use Atk4\Ui\AccordionSection;
9: use Atk4\Ui\Form;
10: use Atk4\Ui\Js\JsBlock;
11:
12: /**
13: * Represents form controls in accordion.
14: */
15: class Accordion extends UiAccordion
16: {
17: /** @var class-string<Form\Layout> */
18: public $formLayout = Form\Layout::class;
19:
20: public Form $form;
21:
22: #[\Override]
23: protected function init(): void
24: {
25: parent::init();
26:
27: // add hook which in case of field error expands respective accordion sections
28: $this->form->onHook(Form::HOOK_DISPLAY_ERROR, static function (Form $form, $fieldName, $str) {
29: // default behavior
30: $jsError = [$form->js()->form('add prompt', $fieldName, $str)];
31:
32: // if a form control is part of an accordion section, it will open that section
33: $section = $form->getControl($fieldName)->getClosestOwner(AccordionSection::class);
34: if ($section) {
35: $jsError[] = $section->getOwner()->jsOpen($section);
36: }
37:
38: return new JsBlock($jsError);
39: });
40: }
41:
42: /**
43: * Return an accordion section with a form layout associate with a form.
44: *
45: * @return Form\Layout
46: */
47: #[\Override]
48: public function addSection($title, \Closure $callback = null, $icon = 'dropdown')
49: {
50: $section = parent::addSection($title, $callback, $icon);
51:
52: return $section->add([$this->formLayout, 'form' => $this->form]);
53: }
54:
55: /**
56: * @param AccordionSection|Form\Layout $section
57: */
58: #[\Override]
59: public function getSectionIdx($section)
60: {
61: if (!$section instanceof AccordionSection) {
62: $section = AccordionSection::assertInstanceOf($section->getOwner());
63: }
64:
65: return parent::getSectionIdx($section);
66: }
67: }
68: