From c79a8486ec2f69e859e6a749fef6467904947b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mor=C3=A1vek?= Date: Sat, 2 May 2020 19:23:26 +0200 Subject: [PATCH] Bootstrap 4: add support for rendering errors in tooltips for all modes --- README.md | 3 + .../FormRendererDI/FormRendererExtension.php | 2 + src/FormRenderer/Bootstrap4Renderer.php | 13 ++ src/FormRenderer/templates/bootstrap4.latte | 14 +- .../FormRendererDI/fixtures/config.neon | 1 + .../FormRenderer/Bootstrap4RendererTest.phpt | 5 + .../bootstrap4-basic-errors-tooltips.html | 144 +++++++++++++++ ...bootstrap4-horizontal-errors-tooltips.html | 170 ++++++++++++++++++ 8 files changed, 345 insertions(+), 7 deletions(-) create mode 100644 tests/FormRenderer/expected/bootstrap4-basic-errors-tooltips.html create mode 100644 tests/FormRenderer/expected/bootstrap4-horizontal-errors-tooltips.html diff --git a/README.md b/README.md index 1e297c0..1a8bc6e 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,8 @@ $renderer->setHorizontalMode(4, 8); // Horizontal form (you can optionally set t Use `$renderer->setRenderValidState(true)` to enable/disable rendering of "valid" form control state for filled inputs after form submission. +In inline mode the error messages are always rendered as tooltips. In the other modes you can switch between standard and tooltip rendering by calling `$renderer->setUseErrorTooltips(true)`. + You can enable the use of [custom form controls](https://getbootstrap.com/docs/4.4/components/forms/#custom-forms) by `$renderer->setUseCustomControls(true)`. To render a checkbox as a switch, you need to set type option: `$checkboxInput->setOption('type', 'switch')`. @@ -119,6 +121,7 @@ formRenderer: bootstrap4: mode: horizontal renderValidState: true + useErrorTooltips: true useCustomControls: true imports: - %appDir%/templates/@form-extras.latte diff --git a/src/Bridges/FormRendererDI/FormRendererExtension.php b/src/Bridges/FormRendererDI/FormRendererExtension.php index 5f7c1c4..85f30cb 100644 --- a/src/Bridges/FormRendererDI/FormRendererExtension.php +++ b/src/Bridges/FormRendererDI/FormRendererExtension.php @@ -45,6 +45,7 @@ public function getConfigSchema(): Nette\Schema\Schema )->default(Bootstrap4Renderer::MODE_BASIC), 'useCustomControls' => Nette\Schema\Expect::bool(false), 'renderValidState' => Nette\Schema\Expect::bool(false), + 'useErrorTooltips' => Nette\Schema\Expect::bool(false), ]); return Nette\Schema\Expect::structure([ @@ -119,6 +120,7 @@ private function setupBootstrap4Renderer(\stdClass $config): void $resultDefinition = $factory->getResultDefinition(); $resultDefinition->setArguments(['templateRendererFactory' => $this->prefix('@templateRendererFactory')]); $resultDefinition->addSetup('setRenderValidState', [$config->renderValidState]); + $resultDefinition->addSetup('setUseErrorTooltips', [$config->useErrorTooltips]); $resultDefinition->addSetup('setUseCustomControls', [$config->useCustomControls]); foreach ($config->imports as $templateFile) { $resultDefinition->addSetup('importTemplate', [$templateFile]); diff --git a/src/FormRenderer/Bootstrap4Renderer.php b/src/FormRenderer/Bootstrap4Renderer.php index ac53645..76e84d7 100644 --- a/src/FormRenderer/Bootstrap4Renderer.php +++ b/src/FormRenderer/Bootstrap4Renderer.php @@ -28,6 +28,8 @@ class Bootstrap4Renderer implements Nette\Forms\IFormRenderer private bool $renderValidState = false; + private bool $useErrorTooltips = false; + private bool $useCustomControls = false; private string $mode = self::MODE_BASIC; @@ -51,6 +53,11 @@ public function setRenderValidState(bool $renderValidState = true): void $this->renderValidState = $renderValidState; } + public function setUseErrorTooltips(bool $useErrorTooltips = true): void + { + $this->useErrorTooltips = $useErrorTooltips; + } + public function setUseCustomControls(bool $useCustomControls = true): void { $this->useCustomControls = $useCustomControls; @@ -80,6 +87,7 @@ public function render(Form $form): string $templateRenderer = $this->getTemplateRenderer(); $template = $templateRenderer->getTemplate(); $template->addFilter('validationClass', new ValidationClassFilter('is-invalid', $this->shouldRenderValidState($form) ? 'is-valid' : null)); + $template->useErrorTooltips = $this->shouldUseErrorTooltips(); $template->useCustomControls = $this->useCustomControls; $template->mode = $this->mode; $template->gridOffsetClass = $this->mode === self::MODE_HORIZONTAL ? sprintf('offset-sm-%d', $this->labelCols) : null; @@ -145,4 +153,9 @@ protected function shouldRenderValidState(Form $form): bool return $this->renderValidState && (bool) $form->isSubmitted(); } + protected function shouldUseErrorTooltips(): bool + { + return $this->mode === self::MODE_INLINE || $this->useErrorTooltips; + } + } diff --git a/src/FormRenderer/templates/bootstrap4.latte b/src/FormRenderer/templates/bootstrap4.latte index bceb134..d48a99c 100644 --- a/src/FormRenderer/templates/bootstrap4.latte +++ b/src/FormRenderer/templates/bootstrap4.latte @@ -88,21 +88,21 @@ {/define} {define #control-type-default} -
+
{include #helpers-override-split, blockNamePrefix => input, control => $control} - {if $mode === inline}{include #control-errors, control => $control}{/if} + {if $useErrorTooltips}{include #control-errors, control => $control}{/if}
{include #control-help, control => $control} - {if $mode !== inline}{include #control-errors, control => $control}{/if} + {if !$useErrorTooltips}{include #control-errors, control => $control}{/if} {/define} {define #control-type-checkboxlist} -
+
{include #helpers-override-split, blockNamePrefix => input, control => $control} - {if $mode === inline}{include #control-errors, control => $control}{/if} + {if $useErrorTooltips}{include #control-errors, control => $control}{/if}
{include #control-help, control => $control} - {if $mode !== inline}{include #control-errors, control => $control}{/if} + {if !$useErrorTooltips}{include #control-errors, control => $control}{/if} {/define} {define #control-type-radio} @@ -110,7 +110,7 @@ {/define} {define #control-errors} - {if $mode === inline} + {if $useErrorTooltips}
{$error}{sep} {/sep}
{else}
{$error}
diff --git a/tests/Bridges/FormRendererDI/fixtures/config.neon b/tests/Bridges/FormRendererDI/fixtures/config.neon index 662b22a..824aeaf 100644 --- a/tests/Bridges/FormRendererDI/fixtures/config.neon +++ b/tests/Bridges/FormRendererDI/fixtures/config.neon @@ -13,6 +13,7 @@ formRenderer: bootstrap4: mode: horizontal useCustomControls: false + useErrorTooltips: false renderValidState: false imports: - %fixturesDir%/form.latte diff --git a/tests/FormRenderer/Bootstrap4RendererTest.phpt b/tests/FormRenderer/Bootstrap4RendererTest.phpt index d70d9d8..061a31f 100644 --- a/tests/FormRenderer/Bootstrap4RendererTest.phpt +++ b/tests/FormRenderer/Bootstrap4RendererTest.phpt @@ -115,6 +115,11 @@ class Bootstrap4RendererTest extends TestCase $form->setRenderer($renderer); HtmlAssert::matchFile(__DIR__ . "/expected/bootstrap4-{$mode}-errors.html", $form->__toString()); + + if ($mode !== FormRenderer\Bootstrap4Renderer::MODE_INLINE) { + $renderer->setUseErrorTooltips(); + HtmlAssert::matchFile(__DIR__ . "/expected/bootstrap4-{$mode}-errors-tooltips.html", $form->__toString()); + } } /** diff --git a/tests/FormRenderer/expected/bootstrap4-basic-errors-tooltips.html b/tests/FormRenderer/expected/bootstrap4-basic-errors-tooltips.html new file mode 100644 index 0000000..b8f5183 --- /dev/null +++ b/tests/FormRenderer/expected/bootstrap4-basic-errors-tooltips.html @@ -0,0 +1,144 @@ +
+
+Form error 1. +
+
+Form error 2. +
+
+Control hidden error 1. +
+
+Control hidden error 2. +
+
+Group 1 +

Group 1 description.

+
+ +
+ +
Control text error 1. Control text error 2.
+
+
+
+ +
+ +
Control textarea error 1. Control textarea error 2.
+
+
+
+Group 2 label +

Group 2 description.

+
+
+
+ + +
+
Control checkbox error 1. Control checkbox error 2.
+
+
+
+ +
+
+ + +
+
+ + +
+
Control checkboxlist error 1. Control checkboxlist error 2.
+
+
+
+ +
+
+ + +
+
+ + +
+
Control radiolist error 1. Control radiolist error 2.
+
+
+
+ +
+ +
Control selectbox error 1. Control selectbox error 2.
+
+
+
+ +
+ +
Control upload error 1. Control upload error 2.
+
+
+
+
+
+ +
+
foo
+
Control foo error 1. Control foo error 2.
+
+
+
+ + + +
+
+ +
+
+ + +
+
+ + +
+
Control inlinecheckboxlist error 1. Control inlinecheckboxlist error 2.
+
+
+
+ +
+
+ + +
+
+ + +
+
Control inlineradiolist error 1. Control inlineradiolist error 2.
+
+
+
+ +
+ +
Control range error 1. Control range error 2.
+
+
+
+
+
+ + +
+
Control switch error 1. Control switch error 2.
+
+Switch description +
+
diff --git a/tests/FormRenderer/expected/bootstrap4-horizontal-errors-tooltips.html b/tests/FormRenderer/expected/bootstrap4-horizontal-errors-tooltips.html new file mode 100644 index 0000000..273f0b4 --- /dev/null +++ b/tests/FormRenderer/expected/bootstrap4-horizontal-errors-tooltips.html @@ -0,0 +1,170 @@ +
+
+Form error 1. +
+
+Form error 2. +
+
+Control hidden error 1. +
+
+Control hidden error 2. +
+
+Group 1 +

Group 1 description.

+
+ +
+
+ +
Control text error 1. Control text error 2.
+
+
+
+
+ +
+
+ +
Control textarea error 1. Control textarea error 2.
+
+
+
+
+Group 2 label +

Group 2 description.

+
+
+
+
+ + +
+
Control checkbox error 1. Control checkbox error 2.
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
Control checkboxlist error 1. Control checkboxlist error 2.
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
Control radiolist error 1. Control radiolist error 2.
+
+
+
+
+ +
+
+ +
Control selectbox error 1. Control selectbox error 2.
+
+
+
+
+ +
+
+ +
Control upload error 1. Control upload error 2.
+
+
+
+
+
+
+ +
+
+
foo
+
Control foo error 1. Control foo error 2.
+
+
+
+
+
+ + + +
+
+
+ +
+
+
+ + +
+
+ + +
+
Control inlinecheckboxlist error 1. Control inlinecheckboxlist error 2.
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
Control inlineradiolist error 1. Control inlineradiolist error 2.
+
+
+
+
+ +
+
+ +
Control range error 1. Control range error 2.
+
+
+
+
+
+
+
+ + +
+
Control switch error 1. Control switch error 2.
+
+Switch description +
+
+