/**
* An extension to Jeremy Kendall's code (http://www.jeremykendall.net/2009/01/19/dynamically-adding-elements-to-zend-form/). Instead of adding single element, the code below attempts to dynamically add a set of elements to a form.
/*
index controller:
<?php
class IndexController extends Zend_Controller_Action
{
public function indexAction ()
{
$form = new Application_Form_Dynamic();
// Form has not been submitted - pass to view and return
if (! $this->getRequest()->isPost()) {
$this->view->form = $form;
return;
}
// Form has been submitted - run data through preValidation()
$form->preValidation($_POST);
// If the form doesn't validate, pass to view and return
if (! $form->isValid($_POST)) {
$this->view->form = $form;
return;
}
// Form is valid
$this->view->form = $form;
}
public function newfieldAction ()
{
$this->_helper->layout->disableLayout();
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('addelm', 'html')->initContext();
$id = $this->_getParam('id', null);
$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;
}
}
?>
Form class:
<?php
class Application_Form_Dynamic extends Zend_Form
{
public function init ()
{
$element = new Zend_Form_Element_Text('name');
$element->setRequired(true);
$this->addElement($element);
$this->addElement('hidden', 'id', array('value' => 1));
$element = new Zend_Form_Element_Button('addentries',
array('id' => 'add'));
$element->setOrder(90);
$this->addElement($element);
$element = new Zend_Form_Element_Button('removeentries',
array('id' => 'remove'));
$element->setOrder(91);
$this->addElement($element);
$element = new Zend_Form_Element_Submit('submit');
$element->setOrder(92);
$this->addElement($element);
}
/**
* After post, pre validation hook
*
* Finds all fields where name includes 'newName' and uses addNewField to add
* them to the form object
*
* @param array $data $_GET or $_POST
*/
public function preValidation (array $data)
{
// array_filter callback
function findForms ($field)
{
// return field names that include 'newName'
if (strpos($field, 'child') !== false) {
return $field;
}
}
$subForms = array_filter(array_keys($data), 'findForms');
$children = array();
foreach ($subForms as $subform) {
if (is_array($data[$subform])) { // subforms added earlier will be passed to post as an array
$children[$subform] = $data[$subform];
}
}
foreach ($children as $key => $fields) {
// strip the id number off of the field name and use it to set new order
$order = ltrim($key, 'child') + 1;
$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);
}
}
?>
index.phtml:
<script type="text/javascript">
$(document).ready(function() {
var id = $("#id").val();
$("#add").on('click', function() {
$.ajax({
type: 'POST',
data: "id=" + id,
url: "<?php echo $this->url(array('action' => 'newfield', 'format' => 'html'));?>",
success: function(data) {
$("#addentries-label").before(data);
$("#id").val(++id);
},
dataType: 'html'
});
});
$("#remove").on('click', function() {
// Get the last used id
var lastId = $("#id").val() - 1;
// Build the attribute search string. This will match the last added dt and dd elements.
// Specifically, it matches any element where the id begins with 'newName<int>-'.
searchString = '*[id^=child' + lastId + '-]';
// Remove the elements that match the search string.
$(searchString).remove();
// Decrement and store id
$("#id").val(--id);
});
});
</script>
<div id="formdiv">
<?php
echo $this->form;
?>
</div>