In Zend Framework 1 I did the following to render a subform in a fieldset:
$row = new Application_Form_Row();
$row->addDecorator('Fieldset');
$this->addSubForm($row, 'row['. $i . ']');
The individual 'row' subforms where then rendered in a fieldset and because of the pseudo array notation of the subform names (row[1], row[2], etc), the posted form data was neatly obtained as an array.
In ZF2 I can only do the rendering at the end, in my view script, with (custom) view helpers and perhaps partial view scripts.
As far as I can see the only way to render my (unknown number of) subforms is to loop through them in my view script.
How can I get my subforms in my view script as an array (or object) to loop through?
This is quite good article about nesting fieldsets and array notation in ZF2 forms:
http://www.michaelgallego.fr/blog/2012/07/04/new-zendform-features-explained/
However there are some limitation worth to read in "Adding new elements dynamically" section.
Related
I've built a Zend_Form_Decorator_Input class which extends Zend_Form_Decorator_Abstract, so that I could customize my form inputs -- works great. I ran into a problem in the decorate class, in trying to get the form name of the element, so as to built a unique id for each field (in case there are multiple forms with identical field names).
There is no method like this: Zend_Form_Element::getForm(); It seems Zend_Form_Decorator_Abstract doesn't have this ability either. Any ideas?
I don't think changing the id from the decorator is the right approach. At the time the decorator is called the element already has been rendered. Thus changing the id would have no effect to the source code. Additionally, as you already have pointed out, the relation between a form and its elements is unidirectional, i.e. (to my best knowledge) there is no direct way to access the form from the element.
So far the bad news.
The good news is, that there actually is a pretty easy solution to your problem: The Zend_Form option elementsBelongTo. It prevents that the same ID is assigned to two form elements that have the same name but belong to different forms:
$form1 = new Zend_Form(array('elementsBelongTo' => 'form1'));
$form1->addElement('Text', 'text1');
$form2 = new Zend_Form(array('elementsBelongTo' => 'form2'));
$form2->addElement('Text', 'text1');
Although both forms have a text field named 'text1', they have different ids: 'form1-text1' and 'form2-text1'. However, there is a major drawback to this: This also changes the name elements in such a way that they are in the format formname[elementname]. Therefore $this->getRequest()->getParam('formname') will return an associative array containing the form elements.
I have 2 Forms, which I am usingain another form to try and keep things DRY.
In this manner:
#Forms/my_form.php
$this->addSubForm(new Form_thisForm(), 'this form');
$this->addSubForm(new Form_thatForm(), 'that form');
//then i add 2 more elements a sort and order element
//then a submit
So in the view where the form is used, all the fields show from all forms included.
However when posting the form data only the fields from Form_thisForm() and the Form_myForm(), ie. the main form, are posting. Data or form element names are not posting from Form_thatForm().
The post only contains variables in the 1st subform and full form. Not the second subform.
I guess your Form_thisForm and Form_thatForm are inherited from Zend_Form, so they also have Form decorator (which basically wraps your subforms in <form> tag).
As a result you have nested <form> tags in your html and this is not valid.
You should inherit your subforms classes from Zend_Form_SubForm - it has no Form decorator by default.
I have a form with collection of subforms - student with different studies - relation manyToOne. I have corrent database schema and entities and form builder works well. I don't know how to append new "study" object. I need to get html tags from somewhere in either cases - when there is at least one "study: object (clone him) or there is no such a one.
Let's assume that study object has 2 fields: name and year. If for a student there is such a record (object) it's first input in generated form has name "student[study][0][name]". And is surrounded by . When I click "Add new study" button I want to duplicate this surrounding div and change id's and name's of html form elements respectively. Is there ready library or method to use?
But there may happen there is no study records so far. So I need to get form from server through ajax call. Unfortunately returned form has inputs with names like "study[name]". Is it possible to render this form similar to first case - I mean "student[study][0][name]". But i'd like to avoid manually generate twig template for form - I prefer
{{ form_widget(form) }}
You should be dealing with data-prototype rather than issuing separate AJAX request. The whole concept of adding/removing subform items is described here:
http://symfony.com/doc/current/reference/forms/types/collection.html#adding-and-removing-items
Obviously, you will need to some JS (jQuery is highly recommended) in order to replicate subform fields.
You should note, however, that data-prototype behaves differently when you initially have empty or non-empty collection. At least I have encountered this weird behavior. As far as I remember, in first your when you say {{ form_rest(form) }} additional DIV is appended with data-prototype attribute consisting of form's HTML. In second case actual HTML (not as an attribute) is appended with ID attribute "form_name_$$name$$" where you need to replace $$name$$ with proper index.
Now, you really should take a look - maybe all this has been fixed in some recent versions but I can't be sure...
Hope this helps a bit...
I have a form here in which there is a textfield which contains a number. In another part of the form there are rows, which coresponds with the number entered. For example 2 = 2 rows etc.
So my idea is to create one row which is duplicated by a javascript. So i must create a input element which name is in a array like name="input[]" how can i do this in Zend Framework?
The only approach i found for this kind of problem is to use subforms. But every Subform has a explicite name which is not in a array.
To make a rendered Zend_Form respond to client-side changes - as in your example, to allow the user to enter the number of rows he wants - you need both client-side and server-handling.
The best example demonstrating the general idea is from Jeremy Kendall:
jeremykendall.net » Blog Archive » Dynamically Adding Elements to Zend_Form
The upshot is that you have client-side code that adds tracks the number of fields and then a preValidation() method that injects the right number of fields into the $form instance before isValid() gets called.
[As noted in the comments there, this preValidation() processing could just be bundled into isValid() so that the controller remains unchanged.]
I have a matrix of checkboxes which I am laying out in a table. I need to pull this matrix into a number of forms, and sometimes multiple times on one form, so I have set it up as a subform.
After much research and deliberation, I decided the best way to decorate the subform was using the viewScript decorator. The code for adding the subform to the form looks something like this:
$this->addSubForm(new Test_Form_Connection_Config_Base(), 'user');
$this->user->setDecorators(array(
array('viewScript', array('viewScript' => '_forms/userConfig.phtml')),
'Description',
'FieldSet',
));
For the most part this works fine however the one problem I have is that I can't get array notation to work. Obviously this becomes a problem when I include the matrix more than once on a particular form.
I tried using setIsArray(true) however this had no effefct. It seems that I need to run the FormElements decorator to get the array notation, but this then gives me a duplicate set of fields on the page (rendered once by FormElements, and once by viewScript).
I could manually construct the name of each element to reflect array notation, but this seems like the long way around. Are there any other options that I'm missing?
Thanks...!
Before using the ViewScript decorator, you should always use the PrepareElements decorator to normalize names.
See http://framework.zend.com/manual/en/zend.form.standardDecorators.html#zend.form.standardDecorators.prepareElements