Adding array elements into a form using Zend 3

You already know how to add elements to a form and attach filters and validators to them, but often you will need to add new elements dynamically or add several elements with the same name.

In HTML it will end up with a name followed by square brackets [] :

<input type="text" name="name[]" />

As an example check out the tutorial on adding rows of inputs dynamically using Jquery. Now you will think :

How do I add array elements into a form using Zend Framework ?

We will build a sample project hosted on Github to describe all the features properly. You can find the project files onto : Fieldset Demo using Zend 3.

The Fieldset demo project will be used later to add other functionalities such as Doctrine 2 integration and so on.

For now you will find the following features :

  • Use of fieldsets within a form
  • Dynamic row data adding using onclick event
  • No database involved
  • Extending Zend FormInput class (View helper)
  • Rendering 1 page form and its result page using a unique view

https://docs.zendframework.com/tutorials/getting-started/modules/

We won’t implement database connection inside this version of the tutorial but a service manager so you can add Doctrine 2 integration later on.

For a full understanding of what’s being involved here, you may browse the documentation on Zend framework

about fieldsets and here for form collections.

There is a lot good stuff in the advanced use of forms page also.

The end result where you click on the Add row button

Zend 3 Fieldsets and form collections - dynamic row data

Let’s design our model structure first so you get a better understanding of the reason why we are setting the form like this.

Model entities schema

Tables Model collection - zend

As an example of use we will take a Recipe as a product which is of one type (or category, ie : breakfast…), the recipe uses several ingredients (item entity) and as main attribute we will assume one ingredient contains gluten :

Model example - ingredients-recipe

Time to code now, we will start with our entities and then attach services to deal with those entities – we name the module : Fieldset.

Category entity (ex : type of recipe)

namespace Fieldset\Entity;

// entity to store categories of products
class Category
{
    /**
     * @var int
     */
    protected $id;
    
    /**
     * @var string
     */
    protected $title;
    
  
    // Construct function with values
    public function __construct($id = null, $title = null) 
    {
    	$this->id = $id;
    	$this->title = $title;
  	
    }
 
    
    public function getId()
    {	
    	return $this->id;
    }
    
    public function getTitle()
    {
    	return $this->title;
    }
    
    
}

We use the constructor to add a new category object.

Same behavior for our attribute class :

namespace Fieldset\Entity;

// entity to store attributes of items - ex : ingredient is having a certain color...
class Attribute
{
    /**
     * @var int
     */
    protected $id;
    
    /**
     * @var string
     */
    protected $title;
    
  
    // Construct function with values
    public function __construct($id = null, $title = null) 
    {
    	$this->id = $id;
    	$this->title = $title;
    	
    }
 
    
    public function getId()
    {	
    	return $this->id;
    }
    
    public function getTitle()
    {
    	return $this->title;
    }
    
    
}

And the item entity :

namespace Fieldset\Entity;

// An item is part of a product - ex : ingredient of a recipe
class Item
{

	/**
	 * @var int
	 */
	protected $id;
	
	/**
	 * @var string
	 */
	protected $name;
	
	/**
	 * @var string
	 */
	protected $description;
	
	/**
	 * @var object refering attribute
	 */
	protected $attribute;
	
	
	// Construct function with values
	public function __construct($id = null, $name = null, $description = null , $attribute = null)
	{
		$this->id = $id;
		$this->name = $name;
		$this->description = $description;
		
		$this->attribute = $attribute;
		
	}
	
	
	public function getId()
	{
		return $this->id;
	}
	
	public function getName()
	{
		return $this->name;
	}
	public function getDescription()
	{
		return $this->description;
	}
	public function getAttribute()
	{
		return $this->attribute;
	}
	
	
}

Then the product entity which contains items :

namespace Fieldset\Entity;

class Product
{
    /**
     * @var int
     */
    protected $id;
    
    /**
     * @var string
     */
    protected $title;
    
    /**
     * @var object refering product category
     */
    protected $categ;
    
    
    /**
     * @var array
     */
    protected $items;
    
    // Construct function with values
    public function __construct($id = null, $title = null, $categ = null) 
    {
    	$this->id = $id;
    	$this->title = $title;
    	$this->categ = $categ;	
      }
 
    
    public function getId()
    {	
    	return $this->id;
    }
    
    public function getTitle()
    {
    	return $this->title;
    }
    
    public function getCateg()
    {
    	return $this->categ;
    }
    
    /**
     * @param array $items
     * @return Product
     */
    public function setItems(array $items)
    {
        $this->items = $items;
        return $this;
    }
    
    /**
     * @return array
     */
    public function getItems()
    {
        return $this->items;
    }
    
}

We will now implement 2 fieldsets which will be attached by our main form. Checkout the definition of a Fieldset from Zend :

Fieldset is a component that contains a reusable set of elements. You will use the Fieldset to create the frontend-input for your backend-models. It is considered good practice to have one Fieldset for every Model of your application.

The advantage of using Fieldsets is that you can include them in different forms and separate coding between classes. And from a form or/and a fieldset you can attach other fieldsets using data collections.

Fieldset and Form classes

Similar to a Zend Form class, fieldsets contain form input parameters and filters we can retrieve within our views.

For the sake of this tutorial we won’t cover filters.

Let’s begin with our Item Fieldset :

namespace Fieldset\Form;

use Fieldset\Entity\Item;
use Zend\Form\Fieldset;
use Zend\Hydrator\ClassMethods;

class ItemFieldset extends Fieldset
{
    public function __construct($name = null, $options = array(), $attributeManager = null)
    {
        
        parent::__construct($name, $options);
        
        $this->setHydrator(new ClassMethods(false));
        $this->setObject(new Item());
        
        $this->add(array(
            'type' => 'number',
            'name' => 'id',
        		//'options' => ['label' => 'Provide a numeric ID']
        ));
        
        $this->add(array(
            'type' => 'text',
            'name' => 'description',
            'options' => array(
              //  'label' => 'Item description'
            )
        ));
        
        $this->add(array(
            'type' => 'text',
            'name' => 'name',
            'options' => array(
               // 'label' => 'Item name'
            )
        ));
        
        // Add "attribute" field
        $this->add([
        		'type'  => 'select',
        		'name' => 'attribute',
        		'attributes' => [
        				'id' => 'attribute',
        		],
        		'options' => [
        				//'label' => 'Attribute',
        				'empty_option' => '-- Please select --',
        				'value_options' => $attributeManager->getAttributes()
        				
        		],
        ]);
        
    }
}

Just a note about the attribute manager instance we will see later : this parameter is passed through the fieldset so we are able to retrieve the set of attributes and provide them to the view in a select input.

Now the product fieldset :

namespace Fieldset\Form;

use Fieldset\Entity\Product;
use Zend\Form\Fieldset;
use Zend\Hydrator\ClassMethods;
use Fieldset\Form\ItemFieldset;

class ProductFieldset extends Fieldset
{
    public function __construct($name = null, $options = array(), $categoryManager = null, $attributeManager = null)
    {
        
        parent::__construct($name, $options);
        
        $this->setHydrator(new ClassMethods(false));
        $this->setObject(new Product());
        
        /* DETAILS about the new product*/
        $this->add(array(
            'type' => 'number',
            'name' => 'id',
            'options' => ['label' => 'Provide a numeric ID']
        ));
        
        
        $this->add(array(
            'type' => 'text',
            'name' => 'title',
            'options' => array(
                'label' => 'Product Title'
            )
        ));
        
        // Add "category" field
        $this->add([
            'type'  => 'select',
            'name' => 'category',
            'attributes' => [
                'id' => 'category',
            ],
            'options' => [
                'label' => 'Category',
                'empty_option' => '-- Please select --',
                'value_options' => $categoryManager->getCategories()
                
            ],
        ]);
        
        

        // Fieldset for ITEM belonging to product - inject the attribute manager to retrieve attributes for each item:
        $item = new ItemFieldset('Item-details',null,$attributeManager);

        $this->add(array(
            'type' => 'collection',
            'name' => 'items',
            'options' => array(
                //https://zendframework.github.io/zend-form/element/collection/
                'should_create_template' => true,
                'allow_add' => true,
                'count' => 2,
                'target_element' =>  $item,
                'template_placeholder' => '__placeholder__',
                
            )
        ));
    }
}

We pass here the category manager and attribute service manager as parameters. The attribute manager instance is used within the call of ou item fieldset.

To bring those fieldsets into action, we attach them to the form as follow :

namespace Fieldset\Form;

use Zend\Form\Form;
use Zend\Form\Element;
use Fieldset\Form\ProductFieldset;
use Zend\Hydrator\ClassMethods;

// One product is defined by a category and list of items
class ProductForm extends Form
{
	
	/**
	 * Category manager.
	 * @var Fieldset\Service\CategoryManager
	 */
	private $categoryManager = null;
	
	/**
	 * Attribute manager.
	 * @var Fieldset\Service\AttributeManager
	 */
	private $attributeManager = null;
	
	
	public function __construct($name = null, $options = array(), $categoryManager = null, $attributeManager = null)
    {
        
    	parent::__construct($name, $options);

    	$this->setHydrator(new ClassMethods(false));
    	
        $this->categoryManager= $categoryManager;
        $this->attributeManager= $attributeManager;
        
        /***CREATE PRODUCT FIELDSET !!! 
         * https://framework.zend.com/manual/2.4/en/modules/zend.form.collections.html
         * ****/
        
        $product = new ProductFieldset('new-product',null, $categoryManager, $attributeManager);
        
        $this->setOptions(['use_as_base_fieldset' => true]);
        $this->add($product);
        
        
        // Submit button :        
        $this->add(array(
            'type' => 'submit',
            'name' => 'submit',
            'attributes' => array(
                'value' => 'Insert new Product'
            )
        ));
    }
}

Service managers

To retrieve and add attributes and categories we use services managers. Here we don’t use Doctrine neither factories but in a later tutorial we will implement Doctrine 2 within ou Fieldset demo example.

The attribute manager :

namespace Fieldset\Service;

use Fieldset\Entity\Attribute;
/**
 * This service is responsible for adding/retrieving attributes
 */
class AttributeManager
{

	protected $attributes = array();
	
	public function __construct($attributes= null)
	{
		$this->attributes= $attributes; 
	}
	
	/**
	 * This method adds a new attribute.
	 */
	
	public function addAttribute($data)
	{
		// Create new category entity.
		$this->attributes[]= new Attribute($data['id'],$data['title']);

	}
	
	/**
	 * Get the list of attributes
	 */
	public function getAttributes() {
		
		$attributes= array();
		
		// transform the object into an array for the select form
		foreach ($this->attributes as $object)
		{
			$attributes[$object->getId()] = $object->getTitle();
		}
		
		return $attributes;
	}
	
}

The category manager :


namespace Fieldset\Service;

use Fieldset\Entity\Category;
/**
 * This service is responsible for adding/editing categories
 */
class CategoryManager
{

	protected $categories = array();
	
	public function __construct($categories = null)
	{
		$this->categories = $categories; 
	}
	
	/**
	 * This method adds a new category.
	 */
	
	public function addCategory($data)
	{
		// Create new category entity.
		$this->categories[]= new Category($data['id'],$data['title']);

	}
	
	/**
	 * Get the list of categories ?
	 */
	public function getCategories() {
		
		$categories = array();
		
		// transform the object into an array for the select form
		foreach ($this->categories as $object)
		{
			$categories[$object->getId()] = $object->getTitle();
		}
		
		return $categories;
	}
	
}

We are almost ready to check the behavior of our form, the controller is here to drive the whole process to the right spots.

The index controller of our fieldset demo form

Inside our controller we will call our form and pass the service managers with which we set up initial data.

namespace Fieldset\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

use Fieldset\Service\CategoryManager;
use Fieldset\Service\AttributeManager;

use Fieldset\Form\ProductForm;

class IndexController extends AbstractActionController
{

    public function indexAction()
    {
    	
    	// Add 3 categories :
    	$categoryManager = new CategoryManager();
    	
    	$data['id'] = 1;
    	$data['title'] = 'Main course';
    	
    	$categoryManager->addCategory($data);
    	
    	$data['id'] = 2;
    	$data['title'] = 'Cake';
    	
    	$categoryManager->addCategory($data);
    	$data['id'] = 3;
    	$data['title'] = 'Aperitif';
    	
    	$categoryManager->addCategory($data);
 
    	
    	// Add 3 attributes :
    	$attributeManager= new AttributeManager();
    	$data['id'] = 1;
    	$data['title'] = 'Color';
    	
    	$attributeManager->addAttribute($data);
    	
    	$data['id'] = 2;
    	$data['title'] = 'Energy';
    	
    	$attributeManager->addAttribute($data);
    	
    	
    	$form = new ProductForm('product-form',null,$categoryManager,$attributeManager);
   	
        return new ViewModel(
            [
                'form' => $form
                
            ]
            
            );
    }
}

Just replace any data you need by whatever is suitable to your needs. Any way you will certainly implement Doctrine to deal with your database instead of these arrays.

Now modify your module.config.php to define your controller as invokable factory :

namespace Fieldset;

use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;

return [
    'router' => [
        'routes' => [
            'fieldset' => [
                'type'    => Segment::class,
                'options' => [
                    'route'       => '/fieldset[/:action[/:id]]',
                    'constraints' => [
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                    ],
                    'defaults'    => [
                        'controller' => Controller\IndexController::class,
                        'action'     => 'index',
                    ],
                ],
            ],
        ],
    ],
    'view_manager' => [
        'template_path_stack' => [
            'fieldset' => __DIR__ . '/../view',
        ],
    ],
    'controllers' => [
        'factories' => [
            Controller\IndexController::class => InvokableFactory::class,
        ],
    ],
    'service_manager' => array(
        ),
    
    'view_helpers'=> [

        'factories' => [
            View\Helper\FormInputTd::class => InvokableFactory::class,
        ],
        'aliases' => [
            'formInputTd' => View\Helper\FormInputTd::class
        ]
        
        
        
    ]
];

In the above code, you will notice the presence of another factory which refers to another class : FormInputTd.

Before we talk about it, check out the view file :

//we call the Form's prepare() method to prepare the form for rendering. Please note that calling this method is very important. If you forget to do that, there may be some undesired rendering problems.
 $form->prepare();
 
 $product = $form->get('new-product');
 
 $product->get('id')->setAttributes([
     'class'=>'form-control',
     'placeholder'=>'01'
 ]);
 
 $product->get('title')->setAttributes([
     'class'=>'form-control',
     'placeholder'=>'Type a title'
 ]);
 
 $product->get('category')->setAttributes([
     'class'=>'form-control',
     'rows'=>2
 ]);
 
 $collection = $product->get('items');
 
 $form->get('submit')->setAttributes(['class'=>'btn btn-primary']);
 ?>






<h1>IndexController::indexAction()</h1>








  Click on the button to add new rows from fieldset


    <?= $this->form()->openTag($form); ?>





<div class="row">
  




<div class="col-md-6">

        
    




<div class="form-group">
      <?= $this->formLabel($product->get('id')); ?>
      <?= $this->formElement($product->get('id')); ?>
      <?= $this->formElementErrors($product->get('id')); ?>
    </div>





        
    




<div class="form-group">
      <?= $this->formLabel($product->get('title')); ?>
      <?= $this->formElement($product->get('title')); ?>
      <?= $this->formElementErrors($product->get('title')); ?>
    </div>





        
    




<div class="form-group">
      <?= $this->formLabel($product->get('category')); ?>
      <?= $this->formElement($product->get('category')); ?>
      <?= $this->formElementErrors($product->get('category')); ?>
    </div>





  </div>





</div>





<a class="btn btn-default" id="add" href="#" role="button"><span class="glyphicon glyphicon-plus"></span>&nbsp;Add row</a> 





<table class="table table-responsive">




<thead>




<tr>




<th>ID</th>








<th>NAME</th>








<th>DESCRIPTION</th>








<th>ATTRIBUTE</th>




</tr>




</thead>




		




<tbody id="fieldset">
	<?php 
	
	//https://framework.zend.com/manual/2.4/en/modules/zend.form.view.helpers.html
	foreach($collection as $var)
	{
	    echo '




<tr>'.$this->formInputTd($var->get('id'));
	    echo '




<td>'.$this->formElement($var->get('name')).'</td>





';
	    echo '




<td>'.$this->formElement($var->get('description')).'</td>





';
	    echo '




<td>'.$this->formElement($var->get('attribute')).'</td>




</tr>





';
	}
	
	
	
	?>			

		</tbody>





	</table>






	<?php // Render the collection template //$this->formCollection()->setTemplateWrapper('<span data-template="%s"></span>');
	//$this->formCollection()->setShouldWrap(false);
	// Change fieldset wrapper to tr rows
	  $this->formCollection()->setWrapper('<tr%4$s>%2$s%1$s%3$s</tr>





');
	
	   echo $this->formCollection()->renderTemplate($collection);

    ?>
	
    <?= $this->formElement($form->get('submit')); ?>    
    <?= $this->form()->closeTag(); ?>

<!-- Jquery script to add one more row inside the table --></pre>
</pre>
<script>$( "#add" ).click(function() {
// Counting rows and add a new one below

var currentCount = $('#fieldset > tr').length;

var template = $('form > span').data('template');
// replace the place holder with the current count

template = template.replace(/__placeholder__/g, currentCount);
$('#fieldset').append(template);

});

</script>
<pre>

If you’ve followed the tutorial on using Jquery to fill in rows, you will understand the structure of the page and also the reason we are taking individual parts of the form to display them. The jquery code is obvious but important as it takes the content of the template provided within span tags attribute.

In the above code you can analyse :

  • how to display a collection of data within a form
  • how to render a template into specific wrappers (I’ve left out comments so you can test on your own the different options)

You will also see the formIntpuTd method we’ve talked about before, it actually replace the formInput provided by Zend/Form which automatically add html tags for default rendering. In this case you want to use td tags instead and to achieve this behavior we chose to extend and override the class as follow :

namespace Fieldset\View\Helper;

use Zend\Form\View\Helper\FormInput;
use Zend\Form\ElementInterface;
use Zend\Form\Exception;

class FormInputTd extends FormInput
{
 

    /**
     * Render a form <input> element from the provided $element
     *
     * @param  ElementInterface $element
     * @throws Exception\DomainException
     * @return string
     */
    public function render(ElementInterface $element)
    {
        $name = $element->getName();
        if ($name === null || $name === '') {
            throw new Exception\DomainException(sprintf(
                '%s requires that the element has an assigned name; none discovered',
                __METHOD__
                ));
        }
        
        $attributes          = $element->getAttributes();
        $attributes['name']  = $name;
        $type                = $this->getType($element);
        $attributes['type']  = $type;
        $attributes['value'] = $element->getValue();
        if ('password' == $type) {
            $attributes['value'] = '';
        }
        
        return '



<td>'.sprintf(
            '<input %s%s', $this->createAttributesString($attributes),
            $this->getInlineClosingBracket()
            ).'</td>




';
    }
   
}

And to register this new view helper, we added it within our module.config.php (see above inside the view_helpers property).

How about the form collection template ?

If you take the demo above into action, you will see that the template collection within span data-template attribute is missing td tags between inputs so how do we implement our FormInputTd within our renderTemplate() method ?

To correct this we need to set our new custom form element input (FormInputTd) as the default one for our form collection, fortunately there is a function allowing us to do that – change the code within your view to match the following :

	  $this->formCollection()->setWrapper('<tr%4$s>%2$s%1$s%3$s</tr>



');
	  
	  // Set the default input helper as our custom formInputTd instead of fromInput
	  $this->formCollection()->setDefaultElementHelper('formInputTd');
	  
	   echo $this->formCollection()->renderTemplate($collection);

Now you are able to add rows to your form :

Fieldset form collection example in zend3

However as there is a select box within our form rows, it’s not currently copied.

The solution is to replace our FormInputTd class by another class extending the Zend FormRow class itself so we have control of the surrounding tags of each row elements.

Extending Zend/FormRow class

/**
 * Extending Form row to apply surrounding tags for elementstring var
 */
namespace Fieldset\View\Helper;

use Zend\Form\View\Helper\FormRow;
use Zend\Form\Element\Button;
use Zend\Form\Element\MonthSelect;
use Zend\Form\Element\Captcha;
use Zend\Form\ElementInterface;
use Zend\Form\Exception;
use Zend\Form\LabelAwareInterface;


class FormRowTd extends FormRow
{
	
	/**
	 * Utility form helper that renders a label (if it exists), an element and errors
	 *
	 * @param  ElementInterface $element
	 * @param  null|string      $labelPosition
	 * @throws \Zend\Form\Exception\DomainException
	 * @return string
	 */
	public function render(ElementInterface $element, $labelPosition = null)
	{
		$escapeHtmlHelper    = $this->getEscapeHtmlHelper();
		$labelHelper         = $this->getLabelHelper();
		$elementHelper       = $this->getElementHelper();
		$elementErrorsHelper = $this->getElementErrorsHelper();
		$label           = $element->getLabel();
		$inputErrorClass = $this->getInputErrorClass();

		
		if (is_null($labelPosition)) {
			$labelPosition = $this->labelPosition;
		}
		if (isset($label) && '' !== $label) {
			// Translate the label
			if (null !== ($translator = $this->getTranslator())) {
				$label = $translator->translate($label, $this->getTranslatorTextDomain());
			}
		}
		// Does this element have errors ?
		if (count($element->getMessages()) > 0 && ! empty($inputErrorClass)) {
			$classAttributes = ($element->hasAttribute('class') ? $element->getAttribute('class') . ' ' : '');
			$classAttributes = $classAttributes . $inputErrorClass;
			$element->setAttribute('class', $classAttributes);
		}
		if ($this->partial) {
			$vars = [
					'element'           => $element,
					'label'             => $label,
					'labelAttributes'   => $this->labelAttributes,
					'labelPosition'     => $labelPosition,
					'renderErrors'      => $this->renderErrors,
			];
			return $this->view->render($this->partial, $vars);
		}
		if ($this->renderErrors) {
			$elementErrors = $elementErrorsHelper->render($element);
		}
		$elementString = '

<td>'.$elementHelper->render($element).'</td>


';
		
		
		
		
		// hidden elements do not need a <label> -https://github.com/zendframework/zf2/issues/5607
		$type = $element->getAttribute('type');
		if (isset($label) && '' !== $label && $type !== 'hidden') {
			$labelAttributes = [];
			if ($element instanceof LabelAwareInterface) {
				$labelAttributes = $element->getLabelAttributes();
			}
			if (! $element instanceof LabelAwareInterface || ! $element->getLabelOption('disable_html_escape')) {
				$label = $escapeHtmlHelper($label);
			}
			if (empty($labelAttributes)) {
				$labelAttributes = $this->labelAttributes;
			}
			// Multicheckbox elements have to be handled differently as the HTML standard does not allow nested
			// labels. The semantic way is to group them inside a fieldset
			if ($type === 'multi_checkbox'
					|| $type === 'radio'
					|| $element instanceof MonthSelect
					|| $element instanceof Captcha
					) {
						$markup = sprintf(
								'

<fieldset>

<legend>%s</legend>


%s</fieldset>


',
								$label,
								$elementString
								);
					} else {
						// Ensure element and label will be separated if element has an `id`-attribute.
						// If element has label option `always_wrap` it will be nested in any case.
						if ($element->hasAttribute('id')
								&& ($element instanceof LabelAwareInterface && ! $element->getLabelOption('always_wrap'))
								) {
									$labelOpen = '';
									$labelClose = '';
									$label = $labelHelper->openTag($element) . $label . $labelHelper->closeTag();
								} else {
									$labelOpen  = $labelHelper->openTag($labelAttributes);
									$labelClose = $labelHelper->closeTag();
								}
								if ($label !== '' && (! $element->hasAttribute('id'))
										|| ($element instanceof LabelAwareInterface && $element->getLabelOption('always_wrap'))
										) {
											$label = '<span>' . $label . '</span>';
										}
										// Button element is a special case, because label is always rendered inside it
										if ($element instanceof Button) {
											$labelOpen = $labelClose = $label = '';
										}
										if ($element instanceof LabelAwareInterface && $element->getLabelOption('label_position')) {
											$labelPosition = $element->getLabelOption('label_position');
										}
										switch ($labelPosition) {
											case self::LABEL_PREPEND:
												$markup = $labelOpen . $label . $elementString . $labelClose;
												break;
											case self::LABEL_APPEND:
											default:
												$markup = $labelOpen . $elementString . $label . $labelClose;
												break;
										}
					}
					if ($this->renderErrors) {
						$markup .= $elementErrors;
					}
		} else {
			if ($this->renderErrors) {
				$markup = $elementString . $elementErrors;
			} else {
				$markup = $elementString;
			}
		}
		return $markup;
	}
	
}
	

Now we are all good :

Extends Zend/formRow

Check out what’s behind the generated form inputs :

Source array form input collection zend fieldset

 

That’s it for this article. Just one more thing and you may browse further tutorials here at Linkstraffic.net, to display the results from the form add the following code inside your index Controller under new ProductForm…:

    	$form = new ProductForm('product-form',null,$categoryManager,$attributeManager);
   	
    	$data = '';
    	
    	// Check if user has submitted the form
    	if ($this->getRequest()->isPost()) {
    		
    		// Fill in the form with POST data
    		$data = $this->params()->fromPost();
    		
    		$form->setData($data);
    		
    		// Validate form
    		if($form->isValid()) {
    			
    			// Get filtered and validated data
    			$data = $form->getData();
    			
    			
    			
    		}
    	}
    	
    	
        return new ViewModel(
            [
                'form' => $form,
            		'data' => $data
                
            ]

And inside your view file, you just need to print the submitted data as follow :


if ($this->data != '')

{

print_r($this->data);

} else {

// rest of your code...

I hope these lines have helped you, we actually dealt with a few features, of course there are alternatives but we are trying to use the best options to proceed (structure and security matters…). If you have any comment or suggestions, drop us a line here.

One response to “Adding array elements into a form using Zend 3”

  1. Adriano says:

    Perfect!!!!

    I was looking for this method $this->formCollection()->renderTemplate($fieldset);

    I just wanted to display the fieldset data-template, I’m building a form with custom html. It worked perfectly here.

    Thank you very much, sorry my English, I’m from Brazil, translated into Google Translate

Leave a Reply

Want more information?

Related links will be displayed here in this section for you to pick up another good spot to get more details about Web marketing and Search Engine Optimization. There will be some sites which we selected to ease the work of any webmaster or/and web marketer on the Internet.

%d bloggers like this: