Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve form JS init selector #2049

Merged
merged 16 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,6 @@ parameters:
-
path: 'src/Crud.php'
message: '~^Call to an undefined method Atk4\\Ui\\AbstractView&Atk4\\Ui\\UserAction\\ExecutorInterface::onHook\(\)\.$~'
-
path: 'src/Form.php'
message: '~^Call to an undefined method Atk4\\Ui\\AbstractView::addButton\(\)\.$~'
-
path: 'src/Form.php'
message: '~^Call to an undefined method Atk4\\Ui\\Js\\JsChain::preventFormLeave\(\)\.$~'
Expand Down
59 changes: 24 additions & 35 deletions src/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,8 @@ protected function init(): void
parent::init();

$this->formElement = View::addTo($this, ['element' => 'form', 'shortName' => 'form'], ['FormElementOnly']);
$this->on('submit', new JsExpression('if (event.target === this) { []; }', [$this->formElement->js()->trigger('submit')]));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main point of this PR, dispatch native event without instantiating Fomantic-UI form behaviour for the native form tag.


// Initialize layout, so when you call addControl / setModel next time, form will know
// where to add your fields.
$this->initLayout();

// set CSS loader for this form
Expand All @@ -146,35 +145,19 @@ protected function init(): void
$this->cb = JsCallback::addTo($this, [], [['desired_name' => 'submit']]);
}

/**
* Initialize form layout. You can inject custom layout
* if you 'layout' => .. to constructor.
*/
protected function initLayout(): void
{
// TODO simplify
if ($this->layout === null) {
$this->layout = [Form\Layout::class]; // @phpstan-ignore-line
}

if (is_string($this->layout) || is_array($this->layout)) { // @phpstan-ignore-line
$this->layout = $this->add(Factory::factory($this->layout, ['form' => $this])); // @phpstan-ignore-line
} elseif (is_object($this->layout)) { // @phpstan-ignore-line
$this->layout->form = $this;
$this->add($this->layout);
} else {
throw (new Exception('Unsupported specification of form layout. Can be array, string or object'))
->addMoreInfo('layout', $this->layout);
if (!is_object($this->layout)) { // @phpstan-ignore-line
$this->layout = Factory::factory($this->layout ?? [Form\Layout::class]); // @phpstan-ignore-line
}
$this->layout->form = $this;
$this->add($this->layout);

// allow to submit by pressing an enter key when child control is focused
$jsSubmit = $this->js(false, null, $this->formElement)->form('submit');
$this->on('submit', new JsExpression('if (event.target === this) { []; }', [$jsSubmit]));

// Add save button in layout
// add save button in layout
if ($this->buttonSave) {
$this->buttonSave = $this->layout->addButton($this->buttonSave);
$this->buttonSave->setAttr('tabindex', 0);
$jsSubmit = $this->js()->form('submit');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invoke div.ui.form submit, thanks to l138, the submit will be sent to the native form tag.

$this->buttonSave->on('click', $jsSubmit);
$this->buttonSave->on('keypress', new JsExpression('if (event.keyCode === 13) { []; }', [$jsSubmit]));
}
Expand Down Expand Up @@ -227,7 +210,7 @@ public function setModel(Model $entity, array $fields = null): void
{
$entity->assertIsEntity();

// Model is set for the form and also for the current layout
// set model for the form and also for the current layout
try {
parent::setModel($entity);

Expand Down Expand Up @@ -492,7 +475,7 @@ protected function loadPost(): void

protected function renderView(): void
{
$this->ajaxSubmit();
$this->setupAjaxSubmit();
if ($this->controlDisplayRules !== []) {
$this->js(true, new JsConditionalForm($this, $this->controlDisplayRules, $this->controlDisplaySelector));
}
Expand All @@ -509,7 +492,9 @@ protected function renderTemplateToHtml(): string

public function fixOwningFormAttrInRenderedHtml(string $html): string
{
return preg_replace('~<(button|fieldset|input|output|select|textarea)(?!\w| form=")~i', '$0 form="' . $this->formElement->name . '"', $html);
return preg_replace_callback('~<(?:button|fieldset|input|output|select|textarea)(?!\w| form=")~i', function ($matches) {
return $matches[0] . ' form="' . $this->getApp()->encodeHtml($this->formElement->name) . '"';
}, $html);
}

/**
Expand Down Expand Up @@ -542,15 +527,19 @@ public function setFormConfig($config)
return $this;
}

/**
* Does ajax submit.
*/
public function ajaxSubmit(): void
public function setupAjaxSubmit(): void
{
$this->js(true)->form(array_merge(['inline' => true, 'on' => 'blur'], $this->formConfig));

$this->js(true, null, $this->formElement)
->api(array_merge(['url' => $this->cb->getJsUrl(), 'method' => 'POST', 'serializeForm' => true], $this->apiConfig));
$this->js(true)->form(array_merge([
'on' => 'blur',
'inline' => true,
], $this->formConfig));

$this->formElement->js(true)->api(array_merge([
'on' => 'submit',
'url' => $this->cb->getJsUrl(),
'method' => 'POST',
'serializeForm' => true,
], $this->apiConfig));

// [name] in selector is to suppress https://github.com/fomantic/Fomantic-UI/commit/facbca003cf0da465af7d44af41462e736d3eb8b
// console errors from Multiline/vue fields
Expand Down
4 changes: 2 additions & 2 deletions src/Table/Column/FilterPopup.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ protected function init(): void
$model->clearData();

return new JsBlock([
$this->form->js(false, null, $this->form->formElement)->form('reset'),
$this->form->js()->form('reset'),
new JsReload($this->reload),
(new Jquery($this->colTrigger))->trigger('click'),
(new Jquery($this->colTrigger))->click(),
]);
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/UserAction/StepExecutorTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ protected function jsSetSubmitButton(View $view, Form $form, string $step): void
? $this->execActionButton
: $this->nextStepButton; // submit on next

$view->js(true, $button->js()->on('click', new JsFunction([], [$form->js(false, null, $form->formElement)->form('submit')])));
$view->js(true, $button->js()->on('click', new JsFunction([], [$form->js()->form('submit')])));
}

/**
Expand Down