diff --git a/src/View/Helper/FormHelper.php b/src/View/Helper/FormHelper.php
index a7984087..891882df 100644
--- a/src/View/Helper/FormHelper.php
+++ b/src/View/Helper/FormHelper.php
@@ -89,10 +89,10 @@ class FormHelper extends Helper
'multicheckboxWrapper' => '
',
'multicheckboxTitle' => '',
'customFileLabel' => '',
- 'customFileFormGroup' => '{{input}}{{label}}
',
+ 'customFileFormGroup' => '{{input}}{{label}}
',
'customFileInputGroupFormGroup' => '{{input}}',
- 'customFileInputGroupContainer' => '{{prepend}}
{{content}}{{label}}' .
- '
{{append}}
',
+ 'customFileInputGroupContainer' =>
+ '{{prepend}}
{{content}}{{label}}
{{append}}
',
'nestingLabel' => '{{hidden}}{{input}}',
'nestingLabelNestedInput' => '{{hidden}}',
];
@@ -127,13 +127,13 @@ class FormHelper extends Helper
'label' => '',
'fileLabel' => '',
'formGroup' => '{{label}}{{input}}{{error}}{{help}}
',
- 'customFileFormGroup' => '{{input}}{{label}}
' .
- '{{error}}{{help}}
',
+ 'customFileFormGroup' =>
+ '{{input}}{{label}}
{{error}}{{help}}
',
'customFileInputGroupFormGroup' => '{{input}}{{error}}{{help}}
',
- 'checkboxFormGroup' => '{{input}}{{label}}
' .
- '{{error}}{{help}}
',
+ 'checkboxFormGroup' =>
+ '{{input}}{{label}}{{error}}{{help}}
',
'customCheckboxFormGroup' => '' .
- '{{input}}{{label}}
{{error}}{{help}}
',
+ '{{input}}{{label}}{{error}}{{help}}',
'datetimeContainer' => '{{content}}
',
'datetimeContainerError' => '_getContext()->hasError($fieldName);
-
$options['label']['templateVars']['groupId'] =
$options['templateVars']['groupId'] =
$this->_domId($fieldName . '-group-label');
@@ -452,6 +450,10 @@ public function control(string $fieldName, array $options = []): string
$options['templates']['label'] = $this->templater()->get('customFileLabel');
$options['templates']['formGroup'] = $this->templater()->get('customFileFormGroup');
+ if ($this->_getContext()->hasError($fieldName)) {
+ $options['templateVars']['invalid'] = $this->_config['errorClass'];
+ }
+
if (
$options['prepend'] ||
$options['append']
@@ -514,6 +516,13 @@ public function control(string $fieldName, array $options = []): string
unset($options['tooltip']);
}
+ if (
+ isset($options['append']) ||
+ isset($options['prepend'])
+ ) {
+ $options['injectErrorClass'] = $this->_config['errorClass'];
+ }
+
$result = parent::control($fieldName, $options);
if ($newTemplates) {
diff --git a/src/View/Widget/InputgroupTrait.php b/src/View/Widget/InputgroupTrait.php
index 60e12c7b..16b2f1db 100644
--- a/src/View/Widget/InputgroupTrait.php
+++ b/src/View/Widget/InputgroupTrait.php
@@ -33,6 +33,7 @@ protected function _withInputGroup(array $data, ContextInterface $context): stri
'prepend' => null,
'append' => null,
'injectFormControl' => true,
+ 'injectErrorClass' => null,
'input' => null,
];
@@ -42,7 +43,8 @@ protected function _withInputGroup(array $data, ContextInterface $context): stri
$prepend = $data['prepend'];
$append = $data['append'];
- unset($data['append'], $data['prepend'], $data['injectFormControl']);
+ $errorClass = $data['injectErrorClass'];
+ unset($data['append'], $data['prepend'], $data['injectFormControl'], $data['injectErrorClass']);
if (isset($data['input'])) {
$input = $data['input'];
@@ -68,6 +70,13 @@ protected function _withInputGroup(array $data, ContextInterface $context): stri
}
if ($prepend || $append) {
+ if (
+ $errorClass &&
+ $context->hasError($data['fieldName'])
+ ) {
+ $attrs['class'][] = $errorClass;
+ }
+
$input = $this->_templates->format('inputGroupContainer', [
'attrs' => $this->_templates->formatAttributes($attrs),
'append' => $append,
diff --git a/tests/TestCase/View/Helper/FormHelperTest.php b/tests/TestCase/View/Helper/FormHelperTest.php
index 62eb0d38..e839be62 100644
--- a/tests/TestCase/View/Helper/FormHelperTest.php
+++ b/tests/TestCase/View/Helper/FormHelperTest.php
@@ -514,10 +514,10 @@ public function testErroredControl()
['label' => ['class' => 'form-check-label', 'for' => 'published']],
'Published',
'/label',
- '/div',
['div' => ['class' => 'invalid-feedback']], 'error message', '/div',
'/div',
'/div',
+ '/div',
];
$this->assertHtml($expected, $result);
}
@@ -1586,12 +1586,12 @@ public function testHelpTextHorizontal()
'label' => ['for' => 'published', 'class' => 'form-check-label'],
'Published',
'/label',
- '/div',
['small' => ['class' => 'form-text text-muted']],
'help text',
'/small',
'/div',
'/div',
+ '/div',
];
$this->assertHtml($expected, $result);
@@ -1801,6 +1801,44 @@ public function testDefaultAlignDatetimeControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignDatetimeControlWithError()
+ {
+ $this->article['errors'] = [
+ 'created' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $now = new \DateTime('now');
+
+ $result = $this->Form->control('created', [
+ 'type' => 'datetime-local',
+ 'value' => $now->format('Y-m-d H:i:s'),
+ ]);
+
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group datetime-local is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'created-group-label',
+ ]],
+ ['label' => ['id' => 'created-group-label']],
+ 'Created',
+ '/label',
+ 'input' => [
+ 'type' => 'datetime-local',
+ 'name' => 'created',
+ 'id' => 'created',
+ 'class' => 'is-invalid form-control',
+ 'value' => $now->format('Y-m-d H:i:s'),
+ ],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignDatetimeControlDate()
{
$this->Form->create($this->article);
@@ -2025,6 +2063,52 @@ public function testHorizontalAlignDatetimeControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignDatetimeControlWithError()
+ {
+ $this->article['errors'] = [
+ 'created' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $now = new \DateTime('now');
+
+ $result = $this->Form->control('created', [
+ 'type' => 'datetime-local',
+ 'value' => $now->format('Y-m-d H:i:s'),
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group row datetime-local is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'created-group-label',
+ ]],
+ ['label' => ['id' => 'created-group-label', 'class' => 'col-form-label col-sm-5']],
+ 'Created',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ 'input' => [
+ 'type' => 'datetime-local',
+ 'name' => 'created',
+ 'id' => 'created',
+ 'class' => 'is-invalid form-control',
+ 'value' => $now->format('Y-m-d H:i:s'),
+ ],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignDatetimeControlDate()
{
$this->Form->create($this->article, [
@@ -2270,6 +2354,47 @@ public function testInlineAlignDatetimeControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ /**
+ * Inline datetime controls currently do not render error messages.
+ */
+ public function testInlineAlignDatetimeControlWithError()
+ {
+ $this->withErrorReporting(0, function () {
+ $this->article['errors'] = [
+ 'created' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+ });
+
+ $now = new \DateTime('now');
+
+ $result = $this->Form->control('created', [
+ 'type' => 'datetime-local',
+ 'value' => $now->format('Y-m-d H:i:s'),
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group datetime-local is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'created-group-label',
+ ]],
+ ['span' => ['id' => 'created-group-label', 'class' => 'sr-only']],
+ 'Created',
+ '/span',
+ 'input' => [
+ 'type' => 'datetime-local',
+ 'name' => 'created',
+ 'id' => 'created',
+ 'class' => 'is-invalid form-control',
+ 'value' => $now->format('Y-m-d H:i:s'),
+ ],
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignDatetimeControlDate()
{
$this->withErrorReporting(0, function () {
@@ -2495,6 +2620,42 @@ public function testDefaultAlignCheckboxControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignCheckboxControlWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'checkbox',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group form-check checkbox is-invalid']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => 0,
+ ]],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignCheckboxControlNestedInput()
{
$this->Form->create($this->article);
@@ -2562,6 +2723,43 @@ public function testDefaultAlignCheckboxControlNestedInputWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignCheckboxControlNestedInputWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'checkbox',
+ 'nestedInput' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group form-check checkbox is-invalid']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => 0,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignCheckboxControlInline()
{
$this->Form->create($this->article);
@@ -2629,6 +2827,43 @@ public function testDefaultAlignCheckboxControlInlineWithTooltip()
$this->assertHtml($expected, $result);
}
+ /**
+ * Inline checkbox controls currently do not render error messages.
+ */
+ public function testDefaultAlignCheckboxControlInlineWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'checkbox',
+ 'inline' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-check form-check-inline checkbox is-invalid']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => 0,
+ ]],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ 'Users',
+ '/label',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignCheckboxControlInlineNestedInput()
{
$this->Form->create($this->article);
@@ -2785,6 +3020,53 @@ public function testHorizontalAlignCheckboxControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignCheckboxControlWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'checkbox',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row checkbox is-invalid']],
+ ['div' => ['class' => 'offset-sm-5 col-sm-7']],
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => 0,
+ ]],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignCheckboxControlNestedInput()
{
$this->Form->create($this->article, [
@@ -2874,8 +3156,11 @@ public function testHorizontalAlignCheckboxControlNestedInputWithTooltip()
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignCheckboxControlInline()
+ public function testHorizontalAlignCheckboxControlNestedInputWithError()
{
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
$this->Form->create($this->article, [
'align' => [
'sm' => [
@@ -2887,27 +3172,31 @@ public function testHorizontalAlignCheckboxControlInline()
$result = $this->Form->control('users', [
'type' => 'checkbox',
- 'inline' => true,
+ 'nestedInput' => true,
]);
$expected = [
- ['div' => ['class' => 'form-group row checkbox']],
+ ['div' => ['class' => 'form-group row checkbox is-invalid']],
['div' => ['class' => 'offset-sm-5 col-sm-7']],
['div' => ['class' => 'form-check']],
['input' => [
+ 'class' => 'is-invalid',
'type' => 'hidden',
'name' => 'users',
'value' => 0,
]],
- ['input' => [
- 'class' => 'form-check-input',
- 'type' => 'checkbox',
- 'name' => 'users',
- 'id' => 'users',
- 'value' => 1,
- ]],
['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
'Users',
'/label',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
'/div',
'/div',
'/div',
@@ -2915,7 +3204,48 @@ public function testHorizontalAlignCheckboxControlInline()
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignCheckboxControlInlineWithTooltip()
+ public function testHorizontalAlignCheckboxControlInline()
+ {
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'checkbox',
+ 'inline' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row checkbox']],
+ ['div' => ['class' => 'offset-sm-5 col-sm-7']],
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => 0,
+ ]],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ 'Users',
+ '/label',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testHorizontalAlignCheckboxControlInlineWithTooltip()
{
$this->Form->create($this->article, [
'align' => [
@@ -2963,6 +3293,54 @@ public function testHorizontalAlignCheckboxControlInlineWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignCheckboxControlInlineWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'checkbox',
+ 'inline' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row checkbox is-invalid']],
+ ['div' => ['class' => 'offset-sm-5 col-sm-7']],
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => 0,
+ ]],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignCheckboxControlInlineNestedInput()
{
$this->Form->create($this->article, [
@@ -3127,6 +3505,46 @@ public function testInlineAlignCheckboxControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ /**
+ * Inline checkbox controls currently do not render error messages.
+ */
+ public function testInlineAlignCheckboxControlWithError()
+ {
+ $this->withErrorReporting(0, function () {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+ });
+
+ $result = $this->Form->control('users', [
+ 'type' => 'checkbox',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-check form-check-inline checkbox is-invalid']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => 0,
+ ]],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users',
+ 'id' => 'users',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users']],
+ 'Users',
+ '/label',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignCheckboxControlNestedInput()
{
$this->withErrorReporting(0, function () {
@@ -3433,6 +3851,67 @@ public function testDefaultAlignRadioControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignRadioControlWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group radio is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
+ 'Users',
+ '/label',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignRadioControlNestedInput()
{
$this->Form->create($this->article);
@@ -3535,6 +4014,68 @@ public function testDefaultAlignRadioControlInline()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignRadioControlInlineWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'inline' => true,
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group radio is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
+ 'Users',
+ '/label',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignRadioControlInlineNestedInput()
{
$this->Form->create($this->article);
@@ -3587,6 +4128,69 @@ public function testDefaultAlignRadioControlInlineNestedInput()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignRadioControlInlineNestedInputWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'inline' => true,
+ 'nestedInput' => true,
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group radio is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
+ 'Users',
+ '/label',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignRadioPerOptionConfiguration()
{
$this->Form->create($this->article);
@@ -3897,7 +4501,208 @@ public function testHorizontalAlignRadioControlWithTooltip()
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignRadioControlNestedInput()
+ public function testHorizontalAlignRadioControlWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group row radio is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testHorizontalAlignRadioControlNestedInput()
+ {
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'nestedInput' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row radio', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ 'option 2',
+ '/label',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testHorizontalAlignRadioControlNestedInputWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'nestedInput' => true,
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group row radio is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testHorizontalAlignRadioControlInline()
{
$this->Form->create($this->article, [
'align' => [
@@ -3914,11 +4719,11 @@ public function testHorizontalAlignRadioControlNestedInput()
1 => 'option 1',
2 => 'option 2',
],
- 'nestedInput' => true,
+ 'inline' => true,
]);
$expected = [
['div' => ['class' => 'form-group row radio', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
- ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
'Users',
'/label',
['div' => ['class' => 'col-sm-7']],
@@ -3927,27 +4732,27 @@ public function testHorizontalAlignRadioControlNestedInput()
'name' => 'users',
'value' => '',
]],
- ['div' => ['class' => 'form-check']],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
- ['input' => [
- 'class' => 'form-check-input',
- 'type' => 'radio',
- 'name' => 'users',
- 'id' => 'users-1',
- 'value' => 1,
- ]],
'option 1',
'/label',
'/div',
- ['div' => ['class' => 'form-check']],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
- ['input' => [
- 'class' => 'form-check-input',
- 'type' => 'radio',
- 'name' => 'users',
- 'id' => 'users-2',
- 'value' => 2,
- ]],
'option 2',
'/label',
'/div',
@@ -3957,8 +4762,11 @@ public function testHorizontalAlignRadioControlNestedInput()
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignRadioControlInline()
+ public function testHorizontalAlignRadioControlInlineWithError()
{
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
$this->Form->create($this->article, [
'align' => [
'sm' => [
@@ -3977,19 +4785,24 @@ public function testHorizontalAlignRadioControlInline()
'inline' => true,
]);
$expected = [
- ['div' => ['class' => 'form-group row radio', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['div' => [
+ 'class' => 'form-group row radio is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
'Users',
'/label',
['div' => ['class' => 'col-sm-7']],
['input' => [
+ 'class' => 'is-invalid',
'type' => 'hidden',
'name' => 'users',
'value' => '',
]],
['div' => ['class' => 'form-check form-check-inline']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'radio',
'name' => 'users',
'id' => 'users-1',
@@ -4001,7 +4814,7 @@ public function testHorizontalAlignRadioControlInline()
'/div',
['div' => ['class' => 'form-check form-check-inline']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'radio',
'name' => 'users',
'id' => 'users-2',
@@ -4011,6 +4824,9 @@ public function testHorizontalAlignRadioControlInline()
'option 2',
'/label',
'/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
'/div',
'/div',
];
@@ -4078,6 +4894,78 @@ public function testHorizontalAlignRadioControlInlineNestedInput()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignRadioControlInlineNestedInputWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'inline' => true,
+ 'nestedInput' => true,
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group row radio is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignRadioControlPerOptionConfiguration()
{
$this->Form->create($this->article, [
@@ -4402,6 +5290,67 @@ public function testInlineAlignRadioControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ /**
+ * Inline radio controls currently do not render error messages.
+ */
+ public function testInlineAlignRadioControlWithError()
+ {
+ $this->withErrorReporting(0, function () {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+ });
+
+ $result = $this->Form->control('users', [
+ 'type' => 'radio',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group radio is-invalid', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['span' => ['id' => 'users-group-label', 'class' => 'sr-only']],
+ 'Users',
+ '/span',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'radio',
+ 'name' => 'users',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignRadioControlWithPerOptionConfiguration()
{
$this->withErrorReporting(0, function () {
@@ -4686,8 +5635,123 @@ public function testDefaultAlignMultipleCheckboxControlWithTooltip()
$this->assertHtml($expected, $result);
}
- public function testDefaultAlignMultipleCheckboxControlNestedInput()
+ public function testDefaultAlignMultipleCheckboxControlWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
+ 'Users',
+ '/label',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testDefaultAlignMultipleCheckboxControlNestedInput()
+ {
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'nestedInput' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group multicheckbox', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
+ 'Users',
+ '/label',
+ ['input' => [
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ 'option 2',
+ '/label',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testDefaultAlignMultipleCheckboxControlNestedInputWithError()
{
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
$this->Form->create($this->article);
$result = $this->Form->control('users', [
@@ -4699,11 +5763,16 @@ public function testDefaultAlignMultipleCheckboxControlNestedInput()
'nestedInput' => true,
]);
$expected = [
- ['div' => ['class' => 'form-group multicheckbox', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['div' => [
+ 'class' => 'form-group multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
'Users',
'/label',
['input' => [
+ 'class' => 'is-invalid',
'type' => 'hidden',
'name' => 'users',
'value' => '',
@@ -4711,7 +5780,7 @@ public function testDefaultAlignMultipleCheckboxControlNestedInput()
['div' => ['class' => 'form-check']],
['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'checkbox',
'name' => 'users[]',
'id' => 'users-1',
@@ -4723,7 +5792,7 @@ public function testDefaultAlignMultipleCheckboxControlNestedInput()
['div' => ['class' => 'form-check']],
['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'checkbox',
'name' => 'users[]',
'id' => 'users-2',
@@ -4732,6 +5801,9 @@ public function testDefaultAlignMultipleCheckboxControlNestedInput()
'option 2',
'/label',
'/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
'/div',
];
$this->assertHtml($expected, $result);
@@ -4788,6 +5860,68 @@ public function testDefaultAlignMultipleCheckboxControlInline()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignMultipleCheckboxControlInlineWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'inline' => true,
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
+ 'Users',
+ '/label',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignMultipleCheckboxControlInlineNestedInput()
{
$this->Form->create($this->article);
@@ -4930,6 +6064,107 @@ public function testDefaultAlignMultipleCheckboxControlOptionGroups()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignMultipleCheckboxControlOptionGroupsWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 'group 1' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'group 2' => [
+ 3 => 'option 3',
+ 4 => 'option 4',
+ ],
+ ],
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'd-block']],
+ 'Users',
+ '/label',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['fieldset' => ['class' => 'form-group']],
+ ['legend' => ['class' => 'col-form-label pt-0']],
+ 'group 1',
+ '/legend',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ '/fieldset',
+ ['fieldset' => ['class' => 'form-group']],
+ ['legend' => ['class' => 'col-form-label pt-0']],
+ 'group 2',
+ '/legend',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-3',
+ 'value' => 3,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-3']],
+ 'option 3',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-4',
+ 'value' => 4,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-4']],
+ 'option 4',
+ '/label',
+ '/div',
+ '/fieldset',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignMultipleCheckboxControlOptionGroupsNestedInput()
{
$this->Form->create($this->article);
@@ -5652,8 +6887,109 @@ public function testDefaultAlignMultipleCheckboxControlOptionsGroupsAndSingleEnt
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignMultipleCheckboxControl()
+ public function testHorizontalAlignMultipleCheckboxControl()
+ {
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row multicheckbox', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testHorizontalAlignMultipleCheckboxControlWithTooltip()
+ {
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [],
+ 'tooltip' => 'Tooltip text',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row multicheckbox', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users ',
+ 'span' => [
+ 'data-toggle' => 'tooltip',
+ 'title' => 'Tooltip text',
+ 'class' => 'fas fa-info-circle',
+ ],
+ '/span',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testHorizontalAlignMultipleCheckboxControlWithError()
{
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
$this->Form->create($this->article, [
'align' => [
'sm' => [
@@ -5671,19 +7007,24 @@ public function testHorizontalAlignMultipleCheckboxControl()
],
]);
$expected = [
- ['div' => ['class' => 'form-group row multicheckbox', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['div' => [
+ 'class' => 'form-group row multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
'Users',
'/label',
['div' => ['class' => 'col-sm-7']],
['input' => [
+ 'class' => 'is-invalid',
'type' => 'hidden',
'name' => 'users',
'value' => '',
]],
['div' => ['class' => 'form-check']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'checkbox',
'name' => 'users[]',
'id' => 'users-1',
@@ -5695,7 +7036,7 @@ public function testHorizontalAlignMultipleCheckboxControl()
'/div',
['div' => ['class' => 'form-check']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'checkbox',
'name' => 'users[]',
'id' => 'users-2',
@@ -5705,13 +7046,16 @@ public function testHorizontalAlignMultipleCheckboxControl()
'option 2',
'/label',
'/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
'/div',
'/div',
];
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignMultipleCheckboxControlWithTooltip()
+ public function testHorizontalAlignMultipleCheckboxControlNestedInput()
{
$this->Form->create($this->article, [
'align' => [
@@ -5724,19 +7068,16 @@ public function testHorizontalAlignMultipleCheckboxControlWithTooltip()
$result = $this->Form->control('users', [
'multiple' => 'checkbox',
- 'options' => [],
- 'tooltip' => 'Tooltip text',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'nestedInput' => true,
]);
$expected = [
['div' => ['class' => 'form-group row multicheckbox', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
- 'Users ',
- 'span' => [
- 'data-toggle' => 'tooltip',
- 'title' => 'Tooltip text',
- 'class' => 'fas fa-info-circle',
- ],
- '/span',
+ 'Users',
'/label',
['div' => ['class' => 'col-sm-7']],
['input' => [
@@ -5744,14 +7085,41 @@ public function testHorizontalAlignMultipleCheckboxControlWithTooltip()
'name' => 'users',
'value' => '',
]],
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ ['input' => [
+ 'class' => 'form-check-input',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ 'option 2',
+ '/label',
+ '/div',
'/div',
'/div',
];
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignMultipleCheckboxControlNestedInput()
+ public function testHorizontalAlignMultipleCheckboxControlNestedInputWithError()
{
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
$this->Form->create($this->article, [
'align' => [
'sm' => [
@@ -5770,12 +7138,17 @@ public function testHorizontalAlignMultipleCheckboxControlNestedInput()
'nestedInput' => true,
]);
$expected = [
- ['div' => ['class' => 'form-group row multicheckbox', 'role' => 'group', 'aria-labelledby' => 'users-group-label']],
+ ['div' => [
+ 'class' => 'form-group row multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
'Users',
'/label',
['div' => ['class' => 'col-sm-7']],
['input' => [
+ 'class' => 'is-invalid',
'type' => 'hidden',
'name' => 'users',
'value' => '',
@@ -5783,7 +7156,7 @@ public function testHorizontalAlignMultipleCheckboxControlNestedInput()
['div' => ['class' => 'form-check']],
['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'checkbox',
'name' => 'users[]',
'id' => 'users-1',
@@ -5795,7 +7168,7 @@ public function testHorizontalAlignMultipleCheckboxControlNestedInput()
['div' => ['class' => 'form-check']],
['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
['input' => [
- 'class' => 'form-check-input',
+ 'class' => 'form-check-input is-invalid',
'type' => 'checkbox',
'name' => 'users[]',
'id' => 'users-2',
@@ -5804,6 +7177,9 @@ public function testHorizontalAlignMultipleCheckboxControlNestedInput()
'option 2',
'/label',
'/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
'/div',
'/div',
];
@@ -5870,6 +7246,77 @@ public function testHorizontalAlignMultipleCheckboxControlInline()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignMultipleCheckboxControlInlineWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'inline' => true,
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group row multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignMultipleCheckboxControlInlineNestedInput()
{
$this->Form->create($this->article, [
@@ -6030,6 +7477,116 @@ public function testHorizontalAlignMultipleCheckboxControlOptionGroups()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignMultipleCheckboxControlOptionGroupsWithError()
+ {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 'group 1' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ 'group 2' => [
+ 3 => 'option 3',
+ 4 => 'option 4',
+ ],
+ ],
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group row multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['label' => ['id' => 'users-group-label', 'class' => 'col-form-label d-block pt-0 col-sm-5']],
+ 'Users',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['fieldset' => ['class' => 'form-group']],
+ ['legend' => ['class' => 'col-form-label pt-0']],
+ 'group 1',
+ '/legend',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ '/fieldset',
+ ['fieldset' => ['class' => 'form-group']],
+ ['legend' => ['class' => 'col-form-label pt-0']],
+ 'group 2',
+ '/legend',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-3',
+ 'value' => 3,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-3']],
+ 'option 3',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-4',
+ 'value' => 4,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-4']],
+ 'option 4',
+ '/label',
+ '/div',
+ '/fieldset',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignMultipleCheckboxControlOptionGroupsNestedInput()
{
$this->Form->create($this->article, [
@@ -6903,6 +8460,71 @@ public function testInlineAlignMultipleCheckboxControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ /**
+ * Inline multi checkbox controls currently do not render error messages.
+ */
+ public function testInlineAlignMultipleCheckboxControlWithError()
+ {
+ $this->withErrorReporting(0, function () {
+ $this->article['errors'] = [
+ 'users' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+ });
+
+ $result = $this->Form->control('users', [
+ 'multiple' => 'checkbox',
+ 'options' => [
+ 1 => 'option 1',
+ 2 => 'option 2',
+ ],
+ ]);
+ $expected = [
+ ['div' => [
+ 'class' => 'form-group multicheckbox is-invalid',
+ 'role' => 'group',
+ 'aria-labelledby' => 'users-group-label',
+ ]],
+ ['span' => ['id' => 'users-group-label', 'class' => 'sr-only']],
+ 'Users',
+ '/span',
+ ['input' => [
+ 'class' => 'is-invalid',
+ 'type' => 'hidden',
+ 'name' => 'users',
+ 'value' => '',
+ ]],
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-1',
+ 'value' => 1,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-1']],
+ 'option 1',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'form-check form-check-inline']],
+ ['input' => [
+ 'class' => 'form-check-input is-invalid',
+ 'type' => 'checkbox',
+ 'name' => 'users[]',
+ 'id' => 'users-2',
+ 'value' => 2,
+ ]],
+ ['label' => ['class' => 'form-check-label', 'for' => 'users-2']],
+ 'option 2',
+ '/label',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignMultipleCheckboxControlWithPerOptionConfiguration()
{
$this->withErrorReporting(0, function () {
@@ -7160,6 +8782,35 @@ public function testDefaultAlignFileControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignFileControlWithError()
+ {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group file is-invalid']],
+ ['label' => ['for' => 'file']],
+ 'File',
+ '/label',
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid form-control-file',
+ ]],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignFileControl()
{
$this->Form->create($this->article, [
@@ -7231,6 +8882,44 @@ public function testHorizontalAlignFileControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignFileControlWithError()
+ {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row file is-invalid']],
+ ['label' => ['class' => 'col-form-label pt-1 col-sm-5', 'for' => 'file']],
+ 'File',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid form-control-file',
+ ]],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignFileControl()
{
$this->withErrorReporting(0, function () {
@@ -7292,6 +8981,39 @@ public function testInlineAlignFileControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testInlineAlignFileControlWithError()
+ {
+ $this->withErrorReporting(0, function () {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+ });
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group file is-invalid']],
+ ['label' => ['class' => 'sr-only', 'for' => 'file']],
+ 'File',
+ '/label',
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid form-control-file',
+ ]],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignRangeControl()
{
$this->Form->create($this->article);
@@ -7357,6 +9079,41 @@ public function testDefaultAlignRangeControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignRangeControlWithError()
+ {
+ $this->article['errors'] = [
+ 'height' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('height', [
+ 'type' => 'range',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ ]);
+ $expected = [
+ 'div' => ['class' => 'form-group range is-invalid'],
+ ['label' => ['for' => 'height']],
+ 'Height',
+ '/label',
+ 'input' => [
+ 'type' => 'range',
+ 'name' => 'height',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'id' => 'height',
+ 'class' => 'is-invalid form-control',
+ ],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignRangeControl()
{
$this->Form->create($this->article, [
@@ -7440,6 +9197,50 @@ public function testHorizontalAlignRangeControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignRangeControlWithError()
+ {
+ $this->article['errors'] = [
+ 'height' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('height', [
+ 'type' => 'range',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ ]);
+ $expected = [
+ 'div' => ['class' => 'form-group row range is-invalid'],
+ ['label' => ['class' => 'col-form-label col-sm-5', 'for' => 'height']],
+ 'Height',
+ '/label',
+ ['div' => ['class' => 'col-sm-7']],
+ 'input' => [
+ 'type' => 'range',
+ 'name' => 'height',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'id' => 'height',
+ 'class' => 'is-invalid form-control',
+ ],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignRangeControl()
{
$this->Form->create($this->article, [
@@ -7509,6 +9310,43 @@ public function testInlineAlignRangeControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testInlineAlignRangeControlWithError()
+ {
+ $this->article['errors'] = [
+ 'height' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+
+ $result = $this->Form->control('height', [
+ 'type' => 'range',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ ]);
+ $expected = [
+ 'div' => ['class' => 'form-group range is-invalid'],
+ ['label' => ['class' => 'sr-only', 'for' => 'height']],
+ 'Height',
+ '/label',
+ 'input' => [
+ 'type' => 'range',
+ 'name' => 'height',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'id' => 'height',
+ 'class' => 'is-invalid form-control',
+ ],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignSubmit()
{
$this->Form->create($this->article);
@@ -9630,26 +11468,104 @@ public function testDefaultAlignCustomRangeControl()
'custom' => true,
]);
$expected = [
- 'div' => ['class' => 'form-group range'],
- ['label' => ['for' => 'height']],
+ 'div' => ['class' => 'form-group range'],
+ ['label' => ['for' => 'height']],
+ 'Height',
+ '/label',
+ 'input' => [
+ 'type' => 'range',
+ 'name' => 'height',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'id' => 'height',
+ 'class' => 'custom-range',
+ ],
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testDefaultAlignCustomRangeControlWithError()
+ {
+ $this->article['errors'] = [
+ 'height' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('height', [
+ 'type' => 'range',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'custom' => true,
+ ]);
+ $expected = [
+ 'div' => ['class' => 'form-group range is-invalid'],
+ ['label' => ['for' => 'height']],
+ 'Height',
+ '/label',
+ 'input' => [
+ 'type' => 'range',
+ 'name' => 'height',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'id' => 'height',
+ 'class' => 'custom-range is-invalid',
+ ],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
+ public function testHorizontalAlignCustomRangeControl()
+ {
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('height', [
+ 'type' => 'range',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'custom' => true,
+ ]);
+ $expected = [
+ 'div' => ['class' => 'form-group row range'],
+ ['label' => ['class' => 'col-form-label col-sm-5', 'for' => 'height']],
'Height',
'/label',
- 'input' => [
- 'type' => 'range',
- 'name' => 'height',
- 'min' => 0,
- 'max' => 10,
- 'step' => 1,
- 'id' => 'height',
- 'class' => 'custom-range',
- ],
+ ['div' => ['class' => 'col-sm-7']],
+ 'input' => [
+ 'type' => 'range',
+ 'name' => 'height',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'id' => 'height',
+ 'class' => 'custom-range',
+ ],
+ '/div',
'/div',
];
$this->assertHtml($expected, $result);
}
- public function testHorizontalAlignCustomRangeControl()
+ public function testHorizontalAlignCustomRangeControlWithError()
{
+ $this->article['errors'] = [
+ 'height' => ['error message'],
+ ];
$this->Form->create($this->article, [
'align' => [
'sm' => [
@@ -9667,7 +11583,7 @@ public function testHorizontalAlignCustomRangeControl()
'custom' => true,
]);
$expected = [
- 'div' => ['class' => 'form-group row range'],
+ 'div' => ['class' => 'form-group row range is-invalid'],
['label' => ['class' => 'col-form-label col-sm-5', 'for' => 'height']],
'Height',
'/label',
@@ -9679,8 +11595,11 @@ public function testHorizontalAlignCustomRangeControl()
'max' => 10,
'step' => 1,
'id' => 'height',
- 'class' => 'custom-range',
+ 'class' => 'custom-range is-invalid',
],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
'/div',
'/div',
];
@@ -9719,6 +11638,44 @@ public function testInlineAlignCustomRangeControl()
$this->assertHtml($expected, $result);
}
+ public function testInlineAlignCustomRangeControlWithError()
+ {
+ $this->article['errors'] = [
+ 'height' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+
+ $result = $this->Form->control('height', [
+ 'type' => 'range',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'custom' => true,
+ ]);
+ $expected = [
+ 'div' => ['class' => 'form-group range is-invalid'],
+ ['label' => ['class' => 'sr-only', 'for' => 'height']],
+ 'Height',
+ '/label',
+ 'input' => [
+ 'type' => 'range',
+ 'name' => 'height',
+ 'min' => 0,
+ 'max' => 10,
+ 'step' => 1,
+ 'id' => 'height',
+ 'class' => 'custom-range is-invalid',
+ ],
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignCustomSelectControl()
{
$this->Form->create($this->article);
@@ -10086,7 +12043,7 @@ public function testDefaultAlignCustomFileControl()
]);
$expected = [
['div' => ['class' => 'form-group file']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10116,7 +12073,7 @@ public function testDefaultAlignCustomFileControlWithTooltip()
]);
$expected = [
['div' => ['class' => 'form-group file']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10132,6 +12089,38 @@ public function testDefaultAlignCustomFileControlWithTooltip()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignCustomFileControlWithError()
+ {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ 'custom' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group file is-invalid']],
+ ['div' => ['class' => 'custom-file is-invalid']],
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid custom-file-input',
+ ]],
+ ['label' => ['class' => 'custom-file-label', 'for' => 'file']],
+ 'File',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testDefaultAlignCustomFileControlInputGroupAppend()
{
$this->Form->create($this->article);
@@ -10144,7 +12133,7 @@ public function testDefaultAlignCustomFileControlInputGroupAppend()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10183,7 +12172,7 @@ public function testDefaultAlignCustomFileControlInputGroupPrepend()
'prepend',
'/span',
'/div',
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10200,6 +12189,46 @@ public function testDefaultAlignCustomFileControlInputGroupPrepend()
$this->assertHtml($expected, $result);
}
+ public function testDefaultAlignCustomFileControlInputGroupWithError()
+ {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article);
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ 'custom' => true,
+ 'append' => 'append',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group file is-invalid']],
+ ['div' => ['class' => 'input-group is-invalid']],
+ ['div' => ['class' => 'custom-file is-invalid']],
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid custom-file-input',
+ ]],
+ ['label' => ['class' => 'custom-file-label', 'for' => 'file']],
+ 'File',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'input-group-append']],
+ ['span' => ['class' => 'input-group-text']],
+ 'append',
+ '/span',
+ '/div',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignCustomFileControl()
{
$this->Form->create($this->article, [
@@ -10218,7 +12247,7 @@ public function testHorizontalAlignCustomFileControl()
$expected = [
['div' => ['class' => 'form-group row file']],
['div' => ['class' => 'offset-sm-5 col-sm-7']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10235,6 +12264,47 @@ public function testHorizontalAlignCustomFileControl()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignCustomFileControlWithError()
+ {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ 'custom' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row file is-invalid']],
+ ['div' => ['class' => 'offset-sm-5 col-sm-7']],
+ ['div' => ['class' => 'custom-file is-invalid']],
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid custom-file-input',
+ ]],
+ ['label' => ['class' => 'custom-file-label', 'for' => 'file']],
+ 'File',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testHorizontalAlignCustomFileControlInputGroupAppend()
{
$this->Form->create($this->article, [
@@ -10255,7 +12325,7 @@ public function testHorizontalAlignCustomFileControlInputGroupAppend()
['div' => ['class' => 'form-group row file']],
['div' => ['class' => 'offset-sm-5 col-sm-7']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10303,7 +12373,7 @@ public function testHorizontalAlignCustomFileControlInputGroupPrepend()
'prepend',
'/span',
'/div',
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10321,6 +12391,55 @@ public function testHorizontalAlignCustomFileControlInputGroupPrepend()
$this->assertHtml($expected, $result);
}
+ public function testHorizontalAlignCustomFileControlInputGroupWithError()
+ {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => [
+ 'sm' => [
+ 'left' => 5,
+ 'middle' => 7,
+ ],
+ ],
+ ]);
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ 'custom' => true,
+ 'append' => 'append',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group row file is-invalid']],
+ ['div' => ['class' => 'offset-sm-5 col-sm-7']],
+ ['div' => ['class' => 'input-group is-invalid']],
+ ['div' => ['class' => 'custom-file is-invalid']],
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid custom-file-input',
+ ]],
+ ['label' => ['class' => 'custom-file-label', 'for' => 'file']],
+ 'File',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'input-group-append']],
+ ['span' => ['class' => 'input-group-text']],
+ 'append',
+ '/span',
+ '/div',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignCustomFileControl()
{
$this->withErrorReporting(0, function () {
@@ -10335,7 +12454,7 @@ public function testInlineAlignCustomFileControl()
]);
$expected = [
['div' => ['class' => 'form-group file']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10351,6 +12470,42 @@ public function testInlineAlignCustomFileControl()
$this->assertHtml($expected, $result);
}
+ public function testInlineAlignCustomFileControlWithError()
+ {
+ $this->withErrorReporting(0, function () {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+ });
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ 'custom' => true,
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group file is-invalid']],
+ ['div' => ['class' => 'custom-file is-invalid']],
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid custom-file-input',
+ ]],
+ ['label' => ['class' => 'custom-file-label', 'for' => 'file']],
+ 'File',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testInlineAlignCustomFileControlInputGroupAppend()
{
$this->withErrorReporting(0, function () {
@@ -10367,7 +12522,7 @@ public function testInlineAlignCustomFileControlInputGroupAppend()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10410,7 +12565,7 @@ public function testInlineAlignCustomFileControlInputGroupPrepend()
'prepend',
'/span',
'/div',
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10427,6 +12582,50 @@ public function testInlineAlignCustomFileControlInputGroupPrepend()
$this->assertHtml($expected, $result);
}
+ public function testInlineAlignCustomFileControlInputGroupWithError()
+ {
+ $this->withErrorReporting(0, function () {
+ $this->article['errors'] = [
+ 'file' => ['error message'],
+ ];
+ $this->Form->create($this->article, [
+ 'align' => 'inline',
+ ]);
+ });
+
+ $result = $this->Form->control('file', [
+ 'type' => 'file',
+ 'custom' => true,
+ 'append' => 'append',
+ ]);
+ $expected = [
+ ['div' => ['class' => 'form-group file is-invalid']],
+ ['div' => ['class' => 'input-group is-invalid']],
+ ['div' => ['class' => 'custom-file is-invalid']],
+ ['input' => [
+ 'type' => 'file',
+ 'name' => 'file',
+ 'id' => 'file',
+ 'class' => 'is-invalid custom-file-input',
+ ]],
+ ['label' => ['class' => 'custom-file-label', 'for' => 'file']],
+ 'File',
+ '/label',
+ '/div',
+ ['div' => ['class' => 'input-group-append']],
+ ['span' => ['class' => 'input-group-text']],
+ 'append',
+ '/span',
+ '/div',
+ '/div',
+ ['div' => ['class' => 'invalid-feedback']],
+ 'error message',
+ '/div',
+ '/div',
+ ];
+ $this->assertHtml($expected, $result);
+ }
+
public function testCustomFileControlInputGroupInferLabelFromField()
{
$this->Form->create($this->article);
@@ -10439,7 +12638,7 @@ public function testCustomFileControlInputGroupInferLabelFromField()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10473,7 +12672,7 @@ public function testCustomFileControlInputGroupInferLabelFromAssociatedField()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'associated[0][file]',
@@ -10510,7 +12709,7 @@ public function testCustomFileControlInputGroupLabelTextFromOptions()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10547,7 +12746,7 @@ public function testCustomFileControlInputGroupLabelAttributes()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10582,7 +12781,7 @@ public function testCustomFileControlInputGroupLabelEscaping()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',
@@ -10615,7 +12814,7 @@ public function testCustomFileControlInputGroupLabelEscaping()
$expected = [
['div' => ['class' => 'form-group file']],
['div' => ['class' => 'input-group']],
- ['div' => ['class' => 'custom-file']],
+ ['div' => ['class' => 'custom-file ']],
['input' => [
'type' => 'file',
'name' => 'file',