laminas / laminas-form

Validate and display simple and complex forms, casting forms to business objects and vice versa
https://docs.laminas.dev/laminas-form/
BSD 3-Clause "New" or "Revised" License
80 stars 52 forks source link

Issue with disabled Checkbox validation #28

Open weierophinney opened 4 years ago

weierophinney commented 4 years ago

I have a form with some single checkboxes. These checkboxes may be disabled depending on other settings in the application. So I want to use disabled checkboxes to indicate that there is a option which is currently not available.

The validation for these disabled checkboxes fails because checkboxes are required (hardcoded) but the hidden elements of the checkboxes are disabled too (so nothing is sent at all and the validation fails).

Do I miss anything? There is no setRequired(false) method for checkboxes...

Checkboxes are hardcoded set to be required here: https://github.com/zendframework/zend-form/blob/master/src/Element/Checkbox.php#L169

The ViewHelper disables the hidden element too here: https://github.com/zendframework/zend-form/blob/master/src/View/Helper/FormCheckbox.php#L61

I think one of this two behaviors should be changed. I would prefer to be able to setRequried(false) a Checkbox.


Originally posted by @Cyberrebell at https://github.com/zendframework/zend-form/issues/110

weierophinney commented 4 years ago

Do I miss anything? There is no setRequired(false) method for checkboxes...

You can use the Zend\InputFilter\InputFilterProviderInterface:

class FooForm extends \Zend\Form\Form
    implements \Zend\InputFilter\InputFilterProviderInterface
{
    public function init()
    {
        $this->add(
            [
                'name'    => 'foo',
                'type'    => 'checkbox',
                'options' => [
                    'label' => 'Foo',
                ],
            ]
        );
    }

    public function getInputFilterSpecification()
    {
        return [
            [
                'name'     => 'foo',
                'required' => false,
            ],
        ];
    }
}

Originally posted by @froschdesign at https://github.com/zendframework/zend-form/issues/110#issuecomment-234157316

weierophinney commented 4 years ago

Thank you. It works to fix my problem. But anyway I think it is counter intuitive default behavior that an disabled checkbox is required and the hidden element is disabled too.


Originally posted by @Cyberrebell at https://github.com/zendframework/zend-form/issues/110#issuecomment-234374442

weierophinney commented 4 years ago

@Cyberrebell

But anyway I think it is counter intuitive default behavior that an disabled checkbox is required and the hidden element is disabled too.

  • If the entire form is disabled, then all form elements must be disabled.
  • If one element is disabled, then all components (hidden elements, all checkboxes of a multicheckbox element, …) must be disabled.

The questions is: If the element is disabled, is the input filter specification needed?!


Originally posted by @froschdesign at https://github.com/zendframework/zend-form/issues/110#issuecomment-234452086

weierophinney commented 4 years ago

What about if the form gets manipulated in the browsers using browsers dev tools?

User changes checked/disabled state, submits the form, form validation succeeds although the checkbox isn't checked but the checkbox is required to be checked. So if the disabled checkbox isn't checked the form validation should fail.


Originally posted by @magicsunday at https://github.com/zendframework/zend-form/issues/110#issuecomment-363701135

weierophinney commented 4 years ago

The value of the disabled checkbox is also not available in the submitted form data.

In Form class:


$this->add([
    'name' => 'export',
    'type' => Checkbox::class,
    'attributes' => [
        'id' => 'export',
        'value' => 1,
        'disabled' => true,
    ],
    'options' => [
        'label' => 'Export',
    ],
]);

// Required in order to disable the hard coded validation of checkboxes
$inputFilter->add([
    'name' => 'export',
    'required' => false,
]);

In my controller:

var_dump($this->getRequest()->getPost()->toArray()) did not contain "export". although it should be always 1 here.


Originally posted by @magicsunday at https://github.com/zendframework/zend-form/issues/110#issuecomment-363702733

weierophinney commented 4 years ago

Ok seems a issue (feature) of HTML, Values from disabled input elements are not submitted.

https://www.w3.org/TR/2016/REC-html51-20161101/sec-forms.html#enabling-and-disabling-form-controls-the-disabled-attribute

https://www.w3.org/TR/html401/interact/forms.html#h-17.12.1

Therefore, it cannot receive user input nor will its value be submitted with the form.


Originally posted by @magicsunday at https://github.com/zendframework/zend-form/issues/110#issuecomment-363706273

weierophinney commented 4 years ago

…values from disabled input elements are not submitted.

Right!

But you can add a hidden element:

$this->add(
    [
        'name'    => 'foo',
        'type'    => Zend\Form\Element\Checkbox::class,
        'options' => [
            'label'              => 'Foo',
            'use_hidden_element' => true,
        ],
    ]
);

In your frontend you can disable the checkbox and the hidden element will be submitted. Can you test this and give us some feedback?


Originally posted by @froschdesign at https://github.com/zendframework/zend-form/issues/110#issuecomment-363714889

waahhhh commented 4 years ago

@weierophinney using $useHiddenElement with true (which is current the default of \Laminas\Form\Element\Checkbox) works fine in my case.

Note: setting the checkbox to disabled within the form like:

$form->add(
  (new Checkbox())
    // ...
    ->setAttribute('disabled', 'disabled')
);

Would disable the hidden element, too - in my case I toggle the checkbox via JavaScript.

froschdesign commented 4 years ago

@waahhhh

Would disable the hidden element, too - in my case I toggle the checkbox via JavaScript.

Please describe your use case and the expected and current behaviour this helps to find a solution. Thanks in advance!