3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Form\View\Helper
;
12 use Zend\Form\Element\Button
;
13 use Zend\Form\Element\MonthSelect
;
14 use Zend\Form\Element\Captcha
;
15 use Zend\Form\ElementInterface
;
16 use Zend\Form\Exception
;
17 use Zend\Form\LabelAwareInterface
;
19 class FormRow
extends AbstractHelper
21 const LABEL_APPEND
= 'append';
22 const LABEL_PREPEND
= 'prepend';
25 * The class that is added to element that have errors
29 protected $inputErrorClass = 'input-error';
32 * The attributes for the row label
36 protected $labelAttributes;
39 * Where will be label rendered?
43 protected $labelPosition = self
::LABEL_PREPEND
;
46 * Are the errors are rendered by this helper?
50 protected $renderErrors = true;
53 * Form label helper instance
57 protected $labelHelper;
60 * Form element helper instance
64 protected $elementHelper;
67 * Form element errors helper instance
69 * @var FormElementErrors
71 protected $elementErrorsHelper;
79 * Invoke helper as functor
81 * Proxies to {@link render()}.
83 * @param null|ElementInterface $element
84 * @param null|string $labelPosition
85 * @param bool $renderErrors
86 * @param string|null $partial
87 * @return string|FormRow
89 public function __invoke(
90 ElementInterface
$element = null,
91 $labelPosition = null,
99 if (is_null($labelPosition)) {
100 $labelPosition = $this->getLabelPosition();
103 if ($renderErrors !== null) {
104 $this->setRenderErrors($renderErrors);
107 if ($partial !== null) {
108 $this->setPartial($partial);
111 return $this->render($element, $labelPosition);
115 * Utility form helper that renders a label (if it exists), an element and errors
117 * @param ElementInterface $element
118 * @param null|string $labelPosition
119 * @throws \Zend\Form\Exception\DomainException
122 public function render(ElementInterface
$element, $labelPosition = null)
124 $escapeHtmlHelper = $this->getEscapeHtmlHelper();
125 $labelHelper = $this->getLabelHelper();
126 $elementHelper = $this->getElementHelper();
127 $elementErrorsHelper = $this->getElementErrorsHelper();
129 $label = $element->getLabel();
130 $inputErrorClass = $this->getInputErrorClass();
132 if (is_null($labelPosition)) {
133 $labelPosition = $this->labelPosition
;
136 if (isset($label) && '' !== $label) {
137 // Translate the label
138 if (null !== ($translator = $this->getTranslator())) {
139 $label = $translator->translate($label, $this->getTranslatorTextDomain());
143 // Does this element have errors ?
144 if ($element->getMessages() && $inputErrorClass) {
145 $classAttributes = ($element->hasAttribute('class') ?
$element->getAttribute('class') . ' ' : '');
146 $classAttributes = $classAttributes . $inputErrorClass;
148 $element->setAttribute('class', $classAttributes);
151 if ($this->partial
) {
153 'element' => $element,
155 'labelAttributes' => $this->labelAttributes
,
156 'labelPosition' => $labelPosition,
157 'renderErrors' => $this->renderErrors
,
160 return $this->view
->render($this->partial
, $vars);
163 if ($this->renderErrors
) {
164 $elementErrors = $elementErrorsHelper->render($element);
167 $elementString = $elementHelper->render($element);
169 // hidden elements do not need a <label> -https://github.com/zendframework/zf2/issues/5607
170 $type = $element->getAttribute('type');
171 if (isset($label) && '' !== $label && $type !== 'hidden') {
172 $labelAttributes = [];
174 if ($element instanceof LabelAwareInterface
) {
175 $labelAttributes = $element->getLabelAttributes();
178 if (! $element instanceof LabelAwareInterface ||
! $element->getLabelOption('disable_html_escape')) {
179 $label = $escapeHtmlHelper($label);
182 if (empty($labelAttributes)) {
183 $labelAttributes = $this->labelAttributes
;
186 // Multicheckbox elements have to be handled differently as the HTML standard does not allow nested
187 // labels. The semantic way is to group them inside a fieldset
188 if ($type === 'multi_checkbox'
190 ||
$element instanceof MonthSelect
191 ||
$element instanceof Captcha
194 '<fieldset><legend>%s</legend>%s</fieldset>',
199 // Ensure element and label will be separated if element has an `id`-attribute.
200 // If element has label option `always_wrap` it will be nested in any case.
201 if ($element->hasAttribute('id')
202 && ($element instanceof LabelAwareInterface
&& ! $element->getLabelOption('always_wrap'))
206 $label = $labelHelper->openTag($element) . $label . $labelHelper->closeTag();
208 $labelOpen = $labelHelper->openTag($labelAttributes);
209 $labelClose = $labelHelper->closeTag();
212 if ($label !== '' && (! $element->hasAttribute('id'))
213 ||
($element instanceof LabelAwareInterface
&& $element->getLabelOption('always_wrap'))
215 $label = '<span>' . $label . '</span>';
218 // Button element is a special case, because label is always rendered inside it
219 if ($element instanceof Button
) {
220 $labelOpen = $labelClose = $label = '';
223 if ($element instanceof LabelAwareInterface
&& $element->getLabelOption('label_position')) {
224 $labelPosition = $element->getLabelOption('label_position');
227 switch ($labelPosition) {
228 case self
::LABEL_PREPEND
:
229 $markup = $labelOpen . $label . $elementString . $labelClose;
231 case self
::LABEL_APPEND
:
233 $markup = $labelOpen . $elementString . $label . $labelClose;
238 if ($this->renderErrors
) {
239 $markup .= $elementErrors;
242 if ($this->renderErrors
) {
243 $markup = $elementString . $elementErrors;
245 $markup = $elementString;
253 * Set the class that is added to element that have errors
255 * @param string $inputErrorClass
258 public function setInputErrorClass($inputErrorClass)
260 $this->inputErrorClass
= $inputErrorClass;
265 * Get the class that is added to element that have errors
269 public function getInputErrorClass()
271 return $this->inputErrorClass
;
275 * Set the attributes for the row label
277 * @param array $labelAttributes
280 public function setLabelAttributes($labelAttributes)
282 $this->labelAttributes
= $labelAttributes;
287 * Get the attributes for the row label
291 public function getLabelAttributes()
293 return $this->labelAttributes
;
297 * Set the label position
299 * @param string $labelPosition
300 * @throws \Zend\Form\Exception\InvalidArgumentException
303 public function setLabelPosition($labelPosition)
305 $labelPosition = strtolower($labelPosition);
306 if (! in_array($labelPosition, [self
::LABEL_APPEND
, self
::LABEL_PREPEND
])) {
307 throw new Exception\
InvalidArgumentException(sprintf(
308 '%s expects either %s::LABEL_APPEND or %s::LABEL_PREPEND; received "%s"',
312 (string) $labelPosition
315 $this->labelPosition
= $labelPosition;
321 * Get the label position
325 public function getLabelPosition()
327 return $this->labelPosition
;
331 * Set if the errors are rendered by this helper
333 * @param bool $renderErrors
336 public function setRenderErrors($renderErrors)
338 $this->renderErrors
= (bool) $renderErrors;
343 * Retrieve if the errors are rendered by this helper
347 public function getRenderErrors()
349 return $this->renderErrors
;
353 * Set a partial view script to use for rendering the row
355 * @param null|string $partial
358 public function setPartial($partial)
360 $this->partial
= $partial;
365 * Retrieve current partial
367 * @return null|string
369 public function getPartial()
371 return $this->partial
;
375 * Retrieve the FormLabel helper
379 protected function getLabelHelper()
381 if ($this->labelHelper
) {
382 return $this->labelHelper
;
385 if (method_exists($this->view
, 'plugin')) {
386 $this->labelHelper
= $this->view
->plugin('form_label');
389 if (! $this->labelHelper
instanceof FormLabel
) {
390 $this->labelHelper
= new FormLabel();
393 if ($this->hasTranslator()) {
394 $this->labelHelper
->setTranslator(
395 $this->getTranslator(),
396 $this->getTranslatorTextDomain()
400 return $this->labelHelper
;
404 * Retrieve the FormElement helper
406 * @return FormElement
408 protected function getElementHelper()
410 if ($this->elementHelper
) {
411 return $this->elementHelper
;
414 if (method_exists($this->view
, 'plugin')) {
415 $this->elementHelper
= $this->view
->plugin('form_element');
418 if (! $this->elementHelper
instanceof FormElement
) {
419 $this->elementHelper
= new FormElement();
422 return $this->elementHelper
;
426 * Retrieve the FormElementErrors helper
428 * @return FormElementErrors
430 protected function getElementErrorsHelper()
432 if ($this->elementErrorsHelper
) {
433 return $this->elementErrorsHelper
;
436 if (method_exists($this->view
, 'plugin')) {
437 $this->elementErrorsHelper
= $this->view
->plugin('form_element_errors');
440 if (! $this->elementErrorsHelper
instanceof FormElementErrors
) {
441 $this->elementErrorsHelper
= new FormElementErrors();
444 return $this->elementErrorsHelper
;