← Back to team overview

anewt-developers team mailing list archive

[Bug 527946] Re: Subform support

 

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
$form->autofill() in that case.

-- 
Subform support
https://bugs.launchpad.net/bugs/527946
You received this bug notification because you are a member of Anewt
developers, which is subscribed to Anewt.



References