How can I in ZF2 create custom form element with custom validator? I want to create custom category picker that uses jQuery and content of this element should be rendered from p
A form element must implement a Zend\Form\ElementInterface
. A default class is the Zend\Form\Element
which you can use as a base form:
<?php
namespace MyModule\Form\Element;
use Zend\Form\Element;
class Foo extends Element
{
}
CUSTOM VALIDATOR
You can let the element directly assign a custom validator. Then you must implement the Zend\InputFilter\InputProviderInterface
:
<?php
namespace MyModule\Form\Element;
use Zend\Form\Element;
use Zend\InputFilter\InputProviderInterface;
use MyModule\InputFilter\Bar as BarValidator;
class Foo extends Element implements InputProviderInterface
{
protected $validator;
public function getValidator()
{
if (null === $this->validator) {
$this->validator = new BarValidator;
}
return $this->validator;
}
public function getInputSpecification()
{
return array(
'name' => $this->getName(),
'required' => true,
'validators' => array(
$this->getValidator(),
),
);
}
}
CUSTOM RENDERING
At this moment it is a bit complex how Zend Framework handles the rendering of custom form element types. Usually, it just returns plain <input type="text">
elements.
There is one option, then you have to override the Zend\Form\View\Helper\FormElement
helper. It is registered as formelement
and you must override this view helper in your custom module:
namespace MyModule;
class Module
{
public function getViewHelperConfig()
{
return array(
'invokables' => array(
'formelement' => 'MyModule\Form\View\Helper\FormElement',
'formfoo' => 'MyModule\Form\View\Helper\FormFoo',
),
);
}
}
Furthermore, every form element in Zend Framework 2 is rendered by a view helper. So you create a view helper for your own element, which will render the element's content.
Then you have to create your own form element helper (MyModule\Form\View\Helper\FormElement
):
namespace MyModule\Form\View\Helper;
use MyModule\Form\Element;
use Zend\Form\View\Helper\FormElement as BaseFormElement;
use Zend\Form\ElementInterface;
class FormElement extends BaseFormElement
{
public function render(ElementInterface $element)
{
$renderer = $this->getView();
if (!method_exists($renderer, 'plugin')) {
// Bail early if renderer is not pluggable
return '';
}
if ($element instanceof Element\Foo) {
$helper = $renderer->plugin('form_foo');
return $helper($element);
}
return parent::render($element);
}
}
As a last step, create your view helper to render this specific form element:
namespace MyModule\Form\View\Helper;
use Zend\Form\ElementInterface;
use Zend\Form\View\Helper\AbstractHelper;
class Foo extends AbstractHelper
{
public function __invoke(ElementInterface $element)
{
// Render your element here
}
}
If you want to render a .phtml file for example for this form element, load it inside this helper:
namespace MyModule\Form\View\Helper;
use Zend\Form\ElementInterface;
use Zend\Form\View\Helper\AbstractHelper;
class Foo extends AbstractHelper
{
protected $script = 'my-module/form-element/foo';
public function render(ElementInterface $element)
{
return $this->getView()->render($this->script, array(
'element' => $element
));
}
}
It will render a my-module/form-element/foo.phtml
and in this script you will have a variable $element
which contains your specific form element.