我读过这篇文章: http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/
这非常有趣,而且效果很好。
我需要使用SubForm做同样的事情。我的意思是当用户按下按钮时,我通过ajax调用一个动作来添加,附加并向我现有的表单显示子表单。
例如:
我有一个表格,用户必须填写他孩子的姓名和姓氏,所以有一个按钮“添加孩子”。当用户按下该按钮时,应将SubForm添加到现有表单并显示。在提交时,它将验证与该文章中的示例完全相同。唯一的区别是,在那里他只添加一个字段。我需要添加一个SubForm,但方式完全相同。
我在我的行动中尝试了以下内容(由Ajax调用):
public function clonerecursivegroupAction()
{
$this->_helper->layout->disableLayout();
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('clonerecursivegroup', 'html')->initContext();
$id = $this->_getParam('id', null);
$subform1 = new Zend_Form_SubForm();
$Element1 = $subform1->createElement('text', 'text1');
$Element1->setLabel('text1')->setRequired(true);
$Element2 = $subform1->createElement('text', 'text2');
$Element2->setLabel('text2')->setRequired(false);
$subform1->addElement($Element1);
$subform1->addElement($Element2);
$this->view->field = $subform1->__toString();
}
这几乎有效 这个动作的视图返回SubForm的html代码,所以在我的ajax调用成功时我只是显示它。
问题是,在提交时它会验证表单,但它已经丢失了刚添加的新子表单。只有一个元素的文章中不会发生这种情况。我想我只需要将SubForm添加到现有的Form中,但是如何?
答案 0 :(得分:2)
将子表单的前缀添加到子表单元素。我使用前缀“child”来表示子表单。每个子表单都将创建为child1,child2等。
public function clonerecursivegroupAction()
{
//.. Other code
$subform = new Zend_Form_SubForm();
$subform->setIsArray(true);
$subform->setName("child$id");
$Element1 = $subform->createElement('text', "newfield$id");
$Element1->setLabel("newfield$id")
->setRequired(true);
$subform->addElement($Element1);
$Element1 = $subform->createElement('text', "nextfield$id");
$Element1->setLabel("nextfield$id")
->setRequired(true);
$subform->addElement($Element1);
$this->view->field = $subform;
// Rest of your statements
}
然后,在preValidation函数中,使用子表单前缀而不是字段名称来过滤子表单:
public function preValidation(array $data) {
// array_filter callback
function findForms($field) {
// return field names that include 'child'
if (strpos($field, 'child') !== false) {
return $field;
}
}
$subForms = array_filter(array_keys($data), 'findForms'); //filter the subform elements
$children = array();
foreach ($subForms as $subform) {
if (is_array($data[$subform])) {
$children[$subform] = $data[$subform];
}
}
//Iterate the children
foreach ($children as $key => $fields) { //$key = subformname, $field=array containing fiend names and values
// strip the id number off of the field name and use it to set new order
$order = ltrim($key, 'child') + 2;
$this->addNewForm($key, $fields, $order);
}
}
添加新表单功能创建每个子表单并附加到主表单:
public function addNewForm($form, $elements, $order) {
$subform = new Zend_Form_SubForm();
$subform->setIsArray(true);
foreach ($elements as $key => $el) {
$Element1 = $subform->createElement('text', $key);
$Element1->setLabel($form.$key)
->setValue($el)
->setRequired(true);
$subform->addElement($Element1);
}
$this->addSubForm($subform, $form, $order);
}
[编辑]对子窗体使用setIsArray会将子窗体的每个元素创建为数组元素。它简化了preValidate功能。编辑代码以使用此功能。
这是另一个使用belongsTo的解决方案,为子表单元素提供数组表示法:http://www.stephenrhoades.com/?p=364