Autonomicpilot

ZF2 Custom Form Element

29 Mar 2013

Quick walk through on creating a simple custom form element that just echos out the value.

I recently needed a way to output plain text as part of a form, that would take a value just like a normal form element would. It’s very similar to something I needed to do in ZF1 and it always weirds me that ZF doesn’t include something like this by default.

We need 4 files to add our new element:

  • The form element
  • The view helper for the element
  • An override of the generic FormElement view helper
  • A Module.php to add our element to the view helper config

I’ve been putting things that tend to be site wide in the application module, or seperate them into another module to be added at the vendor level.

This is our form element, we don’t do anything fancy, it’s just declaring the type.

 1 <?php
 2     namespace Application\Form\Element;
 3 
 4     use Zend\Form\Element;
 5 
 6     class PlainText extends Element
 7     {
 8         protected $attributes = array(
 9             'type' => 'plaintext',
10         );
11     }

This is our view helper, very basic, just returns the value rather than parsing it into some fancy html

 1 <?php
 2 
 3     namespace Application\Form\View\Helper;
 4 
 5     use Zend\Form\View\Helper\AbstractHelper;
 6     use Zend\Form\ElementInterface;
 7 
 8     class FormPlainText extends AbstractHelper {
 9 
10         public function render(ElementInterface $element) {
11         	return $element->getValue();
12         }
13 
14     	public function __invoke(ElementInterface $element = null) {
15     		return $this->render($element);
16     	}
17 
18     }

Here we override the generic FormElement helper so that generic rendering methods, such as $this->formRow will work with our new element.

 1 <?php
 2     namespace Application\Form\View\Helper;
 3 
 4     use Application\Form\Element;
 5     use Zend\Form\View\Helper\FormElement as BaseFormElement;
 6     use Zend\Form\ElementInterface;
 7 
 8     class FormElement extends BaseFormElement
 9     {
10     	public function render(ElementInterface $element)
11     	{
12     		$renderer = $this->getView();
13     		if (!method_exists($renderer, 'plugin')) {
14     			// Bail early if renderer is not pluggable
15     			return '';
16     		}
17 
18     		if ($element instanceof Element\PlainText) {
19     			$helper = $renderer->plugin('form_plain_text');
20     			return $helper($element);
21     		}
22 
23     		return parent::render($element);
24     	}
25     }

And finally we add our bits to the module configuration

 1 <?php
 2     namespace Application;
 3 
 4     use Zend\Mvc\ModuleRouteListener;
 5     use Zend\Mvc\MvcEvent;
 6 
 7     class Module
 8     {
 9 
10         public function getViewHelperConfig()
11         {
12             return array(
13                 'invokables' => array(
14                     'formelement'       => 'Application\Form\View\Helper\FormElement',
15                     'formPlainText'     => 'Application\Form\View\Helper\FormPlainText',
16                 ),
17             );
18         }

Now when we declare our forms we can add a plaintext form element

 1 <?php
 2     $form->add(array(
 3         'type' => 'Application\Form\Element\PlainText',
 4         'name' => 'start_date',
 5         'attributes' => array(
 6             'id' => 'TrialStart',
 7         ),
 8         'options' => array(
 9             'label' => 'Trial Start Date',
10         ),
11     ));

And jobs done, you could add a second element which also renders a hidden field along with the plain text if you need the value being submitted too.

Comments