问题
I want to use a view script to render my zend form as it seems to be the best way to control the layout/design of the form while still using the Zend_Elements classes.
From the view script, I render the element with $this->element->getElement('elementName')
.
I'm having problems with the names of the elements. This is actually a sub-form inside a sub-form inside a form.
When I used the FormElements decorators , the fully qualified name of the elements was form[subForm][subForm][element] , which was good. Wehn I moved to the viewScript decorators, it changed to subForm[subForm][element].
I understood that I need to use the PrepareElements decorator to fix this, but this caused the name to change form[subForm][form][subForm][subForm][elements] (it doubled the first two names in the start).
Any ideas how I should handle this?
Thanks.
UPDATE: I tried to debug PrepareElements and I really don't understand what is doing. It seems like it works ok in the first iteration, but then it adds again the form[subform] prefix when running on one of the middle subforms.
When I'm not using the PrepareElements decorator, I'm just missing the "form" prefix in the names (i.e., instead of form[subForm][element], I get only subForm[element]).
May be I can just fix this somehow?
I tried to change the belongsTo but that only replaced the "subForm" prefix .
It actually seems like what is missing is a belongsTo method on the subForm.
Again, this is all because of the ViewScript decorator. It works fine with the FormElements decorators.
UPDATE 2: Just to clarify, I wouldn't mind this name change, but it causes my fields to not populate when I call form->populate .
Edit: I think that I've narrowed the problem to this: when I get my values back in setDefaults, they are ordered like this:
array(
\"formElements1-name\" => value1... \"subFormName\" => array(
\"parentFormName\" => array(
\"subFormName\" => subForm-values-array
)
)
...
The main problem here is the "parentFormName" => "subFormNAme"..
what does it repeat itself? I'm already in the main form. I'm guessing this is caused because I've set the setElementsBelongTo(formName[subFormName])
, but if I wouldn't do that, then I would get my subform values completely separate from the form,
i.e. values array = array( \"formName\" => array( formValues ), \"subFormNAme\" => array( subFormValues )
, while I exepct it to be
array(
formName => array(
subFormNAme => values-array
)
)...
Is it even possible to make this work?
回答1:
Are you just trying to output your form using <?php echo $this->form; ?>
from your view script?
That works well for simple forms, but for my more complex forms I tend to render each element individually but don't need to use ViewScript decorator on each individual element to do this. Just try something like this from your view script:
<div class="form">
<fieldset>
<legend>Some Form Name</legend>
<form action="<?php echo $this->escape($this->form->getAction()) ?>"
method="<?php echo $this->escape($this->form->getMethod()) ?>"
enctype="multipart/form-data">
<?php echo $this->form->id; // render the id element here ?>
<div class="half">
<?php echo $this->form->name; // render the user name field here ?>
</div>
<div class="half">
<?php echo $this->form->description; // render the description element here ?>
</div>
<div class="clear"></div>
<div class="half">
<?php echo $this->form->address1; // render the address ?>
</div>
<div class="half">
<?php echo $this->form->address2; // render address2 ?>
</div>
<div class="clear"></div>
<div class="third">
<?php echo $this->form->zip; // render zip code ?>
</div>
<div class="third">
<?php echo $this->form->city; // render city ?>
</div>
<div class="third">
<?php echo $this->form->state; // render state ?>
</div>
<div class="clear"></div>
<div class="half">
<?php echo $this->form->country; // render country ?>
</div>
<div class="clear"></div>
<?php echo $this->form->submit; ?>
</form>
</fieldset>
</div>
That is how I do most of my forms because I want to have some elements take up half the width and others the full width.
Surprisingly, the reference guide doesn't tell you that you can do this. I seem to remember a page about it in the past but cannot find it now. When I got started with Zend Framework, I thought the only way I could get my form to output exactly how I wanted was to create complex decorators, but that is not the case.
Matthew Weier O'Phinney has a great blog post on rendering Zend_Form decorators individually which explains what I did above. I hope they add this to the first page of Zend Form because that was discouraging to me at first. The fact is, 90% of my forms render elements individually instead of just echo'ing the form itself.
Note: To stop ZF from enclosing my form elements in the dt and dd tags, I apply this decorator to all of my standard form elements. I have a base form class that I extend all of my forms from so I don't have to repeat this everywhere. This is the decorator for the element so I can use tags to enclose my elements.
public $elementDecorators = array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
array('HtmlTag', array('tag' => 'div', 'class' => 'form-div')),
array('Label', array('class' => 'form-label', 'requiredSuffix' => '*'))
);
For my submit buttons I use
public $buttonDecorators = array(
'ViewHelper',
array('HtmlTag', array('tag' => 'div', 'class' => 'form-button'))
);
回答2:
The current solution is to use the PrepareElements decorator on the subforms with one change - remove the recursive call in the PrepareElements code. Also, no "setElementsBelongTo" is required.
This seem to generate the correct names and ids.
回答3:
The solution would be to use the belongsTo()
form element property.
Example :
new Zend_Form_Element_Text('<elementName>', array('belongsTo' => '<subformName>'))
In this way, the render() method will use a form element name like
name="<subformName>[<elementName>]"
回答4:
I had the same problem and i solved it with a decorator
1 : Create a generic subform with elements
2 : Using a specific decorator with PrepareElements
3 : Change form to an array with setIsArray(true)
Example :
Form
$i = 4;
for($i = 0; $i < $nbReclam ; $i++)
{
$rowForm = new Zend_Form_SubForm($i);
$name= new Zend_Form_Element_Textarea('name');
$rowForm->addElement($name);
$this->addSubForm($rowForm, $i);
}
$this->setDecorators(array(
'PrepareElements',
array('ViewScript', array('viewScript' => 'myDecorator.phtml')),
));
$this->setIsArray(true);
Decorator
<table>
<thead>
<tr>
<th>N°</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<?php foreach ($this->element->getSubForms() as $subForm) : ?>
<tr>
<td> <?php echo $i++?> </td>
<?php foreach ($subForm->getElements() as $row) : ?>
<td><?php echo $row ?></td>
<?php endforeach ?>
</tr>
<?php endforeach ?>
</tbody>
</table>
Enjoy
Sorry for my english, i am french
来源:https://stackoverflow.com/questions/7589603/using-viewscript-decorator-on-nested-subforms-zend-form