Issues

ZF-6909: Disabling a form element should prevent it from accepting a new value

Description

If a Zend Form element is disabled (server-side), it should not accept a value, even if one is posted.

For example, given the following form with "text" element "my_text_field"


$form->my_text_field->disabled = 'disabled';
if ($form->isValid($_POST)) {
    // ...
}

If a value is sent for "my_text_field" in $_POST, the element's value is still updated via the Zend_Form::isValid() call.

I would consider this sort of validation to be on par with a "select" element's default ability to only accept values from its "option" list.

Before you ask "how is a value submitted if the field is disabled", consider how easy client-side manipulation is.

Cheers

Comments

Against what data would you Zend_Form want to check if it was updated?

{quote}Before you ask "how is a value submitted if the field is disabled", consider how easy client-side manipulation is.{quote}

Though that is true, 'disabled' fields are occasionally also used to be changed by javascript, so client-side "manipulation" cannot automatically be assumed.

bq. Against what data would you Zend_Form want to check if it was updated?

It wouldn't have to. What I would propose is some checking in Zend_Form_Element::setValue() or Zend_Form_Element::isValid().

bq. changed by javascript

"select" elements may also have their option list altered client-side. I'd consider handling disabled fields in the same ballpark as handling selects in regards to the submitted data they will or will not accept by default.

Simply mark the element as ignored in addition to disabled; Zend_Form will then not return its value when you request it, nor will it attempt to validate it (which means the value will not be overwritten).

Further on this, if the element is disabled, when validated its value is set to null / empty as disabled form fields are not included in the submission. Setting the ignore flag appears to do nothing as I can't see it used in either Zend_Form::isValid() or Zend_Form_Element::isValid().

I have the same issue than Phil Brown. I use disabled fields to show contextual data but when the isValid method is called, each one is cleared. I don't really understand the purpose of the current behavior so I hope it could be changed.

Matthew, while your Statement is true for getValue(s), in the current implementation ZF-ver-1.10.2, ignored is not honored when validating form data.

What would be the expected behaviour when validating an ignored Element?

1.) Validate true, but do not setValue, 2.) Validate false and do not setValue

When 1.) some might think posted Data is save to process further.

I have been running into the same issue for a while, but I think I just found a solution: use {{isValidPartial()}} instead of {{isValid()}}.

$form->populate($originalData);
$form->my_text_field->disabled = 'disabled';
if ($form->isValid($_POST)) {
    //form is not valid
    //since my_text_field is disabled, it doesn't get submitted in the request
    //isValid() will clear the disabled field value, so now we have to repopulate the field
    $form->my_text_field->value($originalData['my_text_field']);
    $this->view->form = $form;
    return;
}

// if the form is valid, and we call $form->getValues() to save the data, our disabled field value has been cleared!


//...however, if we use isValidPartial()...

$form->populate($originalData);
$form->my_text_field->disabled = 'disabled';
if ($form->isValidPartial($_POST)) {
    //isValidPartial() will NOT clear the disabled field value, so we don't have to repopulate the field!!!
    $this->view->form = $form;
    return;
}

// now if we call $form->getValues(), our data is as we expect

Now that I have found a solution, I am far less frustrated, although I would agree that it doesn't seem right that {{isValid()}} would clear a disabled field's value.

Oops, my code sample was supposed to say

{{if (!$form->isValid($_POST)) { //not valid}}

not

{{if ($form->isValid($_POST)) {}}

and I can't figure out how to edit my comment. Sorry.

In response to Matt:

"Simply mark the element as ignored in addition to disabled; Zend_Form will then not return its value when you request it, nor will it attempt to validate it (which means the value will not be overwritten)."

IsValid does not appear to ignore the elements that are flagged to be ignored. Why is this? You clearly think this is how it is supposed to work (and I agree tremendously) but that is not how it behaves.