Subform support

Bug #527946 reported by Sander van Schouwenburg (Sandworm)
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Anewt
New
Undecided
Unassigned

Bug Description

It is not possible to have several forms with just one submit button. Normally you wouldn't need this, but there are situations where this would be very useful.

One such situation is this: Suppose you have some element with all kinds of annotations, and all those annotations can be in multiple languages. And you want to have one form with the element plus all those annotations in all languages. You could make one form and manually add controls for all languages and give them unique and meaningful id's, and during processing you reconstruct the elements from the id's. But this is very cumbersome. It would be much better to create one form for each language, and have all forms combined into a single form with one submit button.

One way is modifying the renderer so that it doesn't render the actual <form> element, then render all the forms and manually enclose them with a <form> element. But you still have the problem that the names should be unique in the whole form node, and the id's should even be unique in the whole document.

I've worked on this problem and I will submit the results momentarily.

Revision history for this message
Sander van Schouwenburg (Sandworm) (sander-sinaasappel) wrote :
Download full text (3.2 KiB)

My solution is to modify AnewtForm so that it has a 'prefix' element, which is actually an array (as to include nested subforms). If you have a form with the prefix array('foo', 'bar'), and a control named 'foobar', then during the rendering it will have the rendered name 'foo[bar][foobar]' and the id 'foo-bar-foobar'.

So controls have a 'name', which is just the name as normal which is unique in the form. They also have a 'rendered-name', which is the name prefixed by the form prefix as described above. All controls had to be modified to use this rendered-name.

A new control AnewtFormControlSubform is created, which takes an AnewtForm in its constructor. It also needs a renderer some time before rendering (optional constructor argument). It will set the prefix of the subform by its own prefix plus its own name. But because its own prefix is only known when the enclosing form has received its prefix, this is done as late as possible (during rendering, see open issues below).

The AnewtFormRenderer was modified so that hidden controls can be rendered separately. AnewtFormRendererDefault was modified so that all controls can be rendered without an enclosing <form> node. During rendering, the AnewtFormControlSubform will set the prefixes and render the hidden controls and the rest of the controls.

During form submission AnewtForm::autofill() will strip any custom prefixes from the $_GET or $_POST values and fill the form with the rest. AnewtFormControlSubform::set_value($value) will pass the values along to its subform and AnewtFormControlSubform::get_value() will return the form values of the subform. Normal fill handling will take care of the rest.

Validation (is_valid()) will also chain as expected to the subforms.

Processing (handle_(in)valid()) of forms is *not* chained automatically. AnewtFormControlSubform has a method 'process()' which automatically calls 'process' in the subform. This has to be called manually from for example the handle_valid() from the enclosing form (note that process() in the subform will automatically call handle_valid() or handle_invalid() depending on its validity).

Open issues:

Complex controls with multiple input tags are not yet supported in subforms. The only complex control in anewt itself is the AnewtFormControlFileUpload. The main problem here is that it creates extra controls postfixed with an attribute (like "-remove"), but that will create a name like "foo[bar][foobar]-remove", which php does not process. The simple solution (which also avoids name conflicts) will be to change them so that postfixed like "[remove]", but then the original input element must also be postfixed by something.

The prefix for the AnewtForm is set with AnewtFormControlSubform->set_prefix(), which is called during AnewtFormControlSubForm->build_widget(). So before rendering, the prefixes will not be correct unless you manually call set_prefix().

Just realized but not tested: A subform containing only controls which may not be submitted (like checkboxes and multi-select controls) will probably fail on filling when nothing is submitted (i.e.: all the checkboxes are off). Simple workaround for now is to ignore the value of...

Read more...

Revision history for this message
Sander van Schouwenburg (Sandworm) (sander-sinaasappel) wrote :

 1491 Sander van Schouwenburg 2010-02-25
      [form] Merged subform support from a private project.

      See also bug #527946

Apparently the merge info has gotten lost in the merge, so here is the log from the merge source:

 1736 ontwerp 2010-01-15
      [form] Form prefix support

      Adds prefix support to forms. A form can have a prefix, which is an array of
      strings. All form control names will be prefixed with the given prefix during
      rendering.

      This is best explained by example. Suppose a form control has the name
      'mytext', and the form has the prefix array('foo', 'bar'), then the name in the
      output will be 'foo[bar][mytext]'.

      This is necessary for the upcoming patch for subform controls.

      Note that any custom controls which directly extend AnewtFormControl must
      be patched to use the new $control->get('rendered-name');

      Complex controls like AnewtFormControlFileUpload currently do not support
      prefixes. They will however work fine when not using prefixes.

 1737 ontwerp 2010-01-15
      [form] Subform support

      A new form control AnewtFormControlSubform can incorporate another form into a
      larger form. This is done by using prefixes to prefix all controls of the
      subform. It works recursively.

      AnewtFormRendererBase and AnewtFormRendererDefault are modified so that it is
      possible to render a form without the <form> tags.

      Note that file upload controls, and other controls which do not handle prefixes
      correctly will not work in subforms. They will however work fine in the main
      form.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.