Issues

ZF-7308: Zend_Dojo_Form requires an id or name attribute to be initialized properly in programmatic mode

Description

It seems that the NumbersSpinner issue might be a dojo-issue, I've posted this ticket: http://bugs.dojotoolkit.org/ticket/9643

This leaves the issue with the dojo form not being connected to the form when using Zend_Dojo_View_Helper_Dojo::setUseProgrammatic();

I've debugged and found the cause being that the form can't be without an id or name attrib:


The error is due to this part: {"id":null,"params":{"dojoType":"dijit.form.Form"}}. The id cannot be null since the dojo.byId then can't find the form.

My suggestion is to:


    public function getName(){
        $name = parent::getName();
        if($name === null){
            $name = __CLASS__ . "_timestamp_" .time();
        }
        return $name;
    }

The alternative is to throw an exception or warning when not providing a Zend_Dojo_Form with an id or name. Another possibility that applies to my specific code is to use the ini-file data as name of the form:


demo.test_element_form.method = "post"
demo.test_element_form.class = "zend_form"

Where the form name obviously is "test_element_form".

Original bug report: A Zend_Dojo_Form isn't submittable if a NumberSpinner element is set to null, pressing the submit button gives no response. After some searching I found this comment on Dojo's homepage about the required vale that explains this odd behavior: ??Defaults to true in NumberSpinner because the arrows won't work otherwise.??

See http://dojotoolkit.org/book/dojo-book-0-9/… for details

Suggestion: - Improve doc - add a comment about this in the docs - Disable false - disable the required false option for this element

Comments

Just noticed that this seems to be an on-and-off issue, I've been able to use the NumberSpinner in forms created from ini-files without any issues and without being forced to add a required.

My latest situation where this problem reappears is when I have a form created from ini-files where there are subforms with the NumberSpinners in them. This is all a little strange, hard to understand - probably a dojo error since the submit button doesn't respond.

Here is an example of my current code:


[followup3]
; general form metainformation
demo.followup3.method = "post"
demo.followup3.class = "zend_form"

; initials element
demo.followup3.elements.initials.type = "TextBox"
demo.followup3.elements.initials.options.label = "Initials"
demo.followup3.elements.initials.options.name = "initials"
demo.followup3.elements.initials.options.required = true
demo.followup3.elements.initials.options.prefixPath.validate.prefix = "Max_Validate"
demo.followup3.elements.initials.options.prefixPath.validate.path = "Max/Validate/"
demo.followup3.elements.initials.options.prefixPath.validate.type = "validate"
demo.followup3.elements.initials.options.validators.checkDemoInitials = "checkDemoInitials"
demo.followup3.elements.initials.options.validators.alnum.validator = "alnum"
demo.followup3.elements.initials.options.validators.strlen.validator = "StringLength"
demo.followup3.elements.initials.options.validators.strlen.options.min = "1"
demo.followup3.elements.initials.options.validators.strlen.options.max = "10"

; followup3_date element
demo.followup3.elements.followup_date.type = "DateTextBox"
demo.followup3.elements.followup_date.options.label = "Followup date"
demo.followup3.elements.followup_date.options.name = "followup_date"
demo.followup3.elements.followup_date.validators.date.validator = "date"

; submit element
demo.followup3.elements.submit.type = "submit"
demo.followup3.elements.submit.name = "save"

[followup3_eq5d]
; general form metainformation
demo.followup3_eq5d.method = "post"
demo.followup3_eq5d.class = "zend_form"

; mobility element
demo.followup3_eq5d.elements.mobility.type = "RadioButton"
demo.followup3_eq5d.elements.mobility.options.label = "Mobility"
demo.followup3_eq5d.elements.mobility.options.name = "mobility"
demo.followup3_eq5d.elements.mobility.options.multiOptions.1 = "I have no problems in walkning about"
demo.followup3_eq5d.elements.mobility.options.multiOptions.2 = "I have some problems in walking about"
demo.followup3_eq5d.elements.mobility.options.multiOptions.3 = "I am confined to bed"

; current_health_state element
demo.followup3_eq5d.elements.current_health_state.type = "NumberSpinner"
demo.followup3_eq5d.elements.current_health_state.options.label = "Health state"
demo.followup3_eq5d.elements.current_health_state.options.name = "current_health_state"
demo.followup3_eq5d.elements.current_health_state.options.places = 0
demo.followup3_eq5d.elements.current_health_state.options.min = "0"
demo.followup3_eq5d.elements.current_health_state.options.max = "100"
demo.followup3_eq5d.elements.current_health_state.options.smallDelta = "1"
demo.followup3_eq5d.elements.current_health_state.options.largeDelta = "10"
; the filtering below is for getting a null if the value is empty - for some reason it doesn't do that for me
; without some extra filtering
demo.followup3_eq5d.elements.current_health_state.options.prefixPath.filter.prefix = "Max_Filter"
demo.followup3_eq5d.elements.current_health_state.options.prefixPath.filter.path = "Max/Filter/"
demo.followup3_eq5d.elements.current_health_state.options.prefixPath.filter.type = "filter"
demo.followup3_eq5d.elements.current_health_state.options.filters.setNull = "setNull"

; submit element
demo.followup3_eq5d.elements.submit.type = "submit"
demo.followup3_eq5d.elements.submit.name = "save"

Then some code



Zend_Loader::loadClass('Zend_Dojo_Form');
$form  = new Zend_Dojo_Form();
$form->setMethod('post');
$form->setAttribs(array(
            'name'  => 'masterForm',
            'method' => 'post',
));

$form->setDecorators(
array(
    'FormElements',
    array('TabContainer',
        array(
        'id' => 'tabContainer',
        'style' => 'width: auto; max-width: 800px; height: 600px',
        'dijitParams' => array(
            'tabPosition' => 'top'
        ))
    ),
    'DijitForm',
));

...stuff...

Zend_Loader::loadClass("Zend_Dojo_Form_SubForm");
foreach ($this->view->group_tables[$group_name] as $table_name) {
    $config = new Zend_Config_Ini($config_file_name, $table_name);
    $new_subform= new Zend_Dojo_Form_SubForm($config->$study_name->$table_name);
    $new_subform->setAttribs(
        array(
            'name'   => $table_name,
            'legend' => $this->view->all_table_key_names[$table_name],
            'dijitParams' => array(
                'title' => $this->view->all_table_key_names[$table_name],
            ),
            'class' => 'zend_form'
        )
    );

    $data = $model->getSubjectArray($subject_id, $table_name);
    $new_subform->setDefaults($data);
    $form->addSubForm($new_subform, $table_name);
}

I've tried to remove the unnecessary stuff but if it's still unreadable (or due to that) then tell me to re-post.

The reason for the tabbed and non-tabbed issue seems to be related to the the Zend_Dojo_View_Helper_Dojo::setUseDeclarative()/setUseProgrammatic(): - With declarative use the onSubmit event is connected - With programmatic use the onSubmit event is only connected when I use a form in a tabbed manner as above

The problem with NumberSpinner is connected to the onSubmit event so even though part of the mystery is solved the main problem remains

Sorry for the somewhat messy bug report, hopefully it is now much clearer what needs to be done.

It is important issue. Because Zend_Dojo_Form's without "name" works differently in programmatic and declarative modes

ID is enforced during construct, orginal solution to override the Zend_Form::getName method was unstable. Creating two forms quickly after each other could result in duplicate Id's. In addition, the return value of getName() would not be consistent.

Patch is only partial, since IE (atleast 9) will still submit the form even though it is empty/not validated correctly.. setting the name attribute in addition to the ID did not resolve this

The provided solution seemed like the incorrect place to do this; if the form name is passed in or changed later, it can cause issues. The more appropriate location seemed to be during decoration, and as such, I've added some code to the DijitForm decorator to generate a name if none is present.

The relevant commit is r23932; please check. If it works, let me know so I can merge it to the release branch; if not, please indicate what's failing -- e.g., if the generation of the dijit.form.Form ID is missing, etc.