2013-04-28 2 views
1

Я использую следующий код для добавления электронной почты элемента в моем Zend Framework 2 формы:добавить требуется суффикс ZF2 формы этикетки элемента

$form->add(array(
    'type' => 'Zend\Form\Element\Email', 
    'name' => 'email', 
    'options' => array(
     'label' => 'Email' 
    ), 
)); 

По умолчанию метод getInputSpecification() этот элемент множества, необходимые для истинно , Но элемент-элемент не содержит требуемого свойства, и, следовательно, разметка тоже не существует.

Как я могу добавить разметку в мою форму для моего css, чтобы иметь возможность добавить необходимый суффикс? Или, по крайней мере: как может пользовательский помощник просмотра захватить «требуемую» настройку?

Я понимаю, что могу просто добавить требуемый атрибут, но это не кажется правильным, поскольку он может выйти из синхронизации с настройкой внутреннего элемента.

ответ

2

Вы в значительной степени правильно поняли. Для этого вам определенно нужен ваш собственный ViewHelper. Самый простой способ достичь этого - продлить от Zend\Form\View\Helper\FormLabel и перезаписать функцию __invoke(). Это просто быстро попробовать, но я предполагаю, что это имеет потенциал для правильной работы;)

public function __invoke(ElementInterface $element = null, $labelContent = null, $position = null) 
{ 
    // Implement all default lines of Zend\Form\View\Helper\FormLabel 

    // Set $required to a default of true | existing elements required-value 
    $required = ($element->hasAttribute('required') ? $element->getAttribute('required') : true);   

    if (true === $required) { 
     $labelContent = sprintf(
      '<span class="im-required">(*)</span> %s', 
      $labelContent 
     ); 
    } 

    return $openTag . $labelContent . $this->closeTag(); 
} 

Не забудьте зарегистрировать ваш собственный ViewHelper в вашем Module#getViewHelperConfig(), как это:

public function getViewHelperConfig() 
{ 
    return array(
     'factories' => array(
      'myFormLabel' => function($sm) { 
       return new Mynamespace\Form\View\Helper\MyFormLabel; 
      }, 
     ), 
    ); 
} 

Я на самом деле вроде бы удивился, что такая вещь не реализована, хотя я уверен, что есть причина для этого :)

+0

См. Последнюю строку моего вопроса: добавив обязательный атрибут, который вы должны указать для регистрации «required»: один в форме и один в inputfilter. Это не похоже на путь. – tihe

+0

Постарайтесь понять логику этого. 'Attribute [required]' элемента формы представляет HTML-атрибут ''. «InputFilter» заботится о вашей бизнес-логике. Это две совершенно разные проблемы, даже если у них есть сенсорные точки. – Sam

+0

Валидация и разметка действительно представляют собой две отдельные проблемы. Но здесь мы говорим о валидации, приводящей к содержанию. Если вы их отделите, вы делаете что-то вручную (с риском получения проверки и содержимого из синхронизации), что может быть сделано автоматически. – tihe

0

Хорошо, поэтому мне было больно смотреть дальше ... поэтому я просто проанализировал имя элемента, чтобы найти самую глубокую строку между скобками ... вот мои viewhelpers, чтобы отобразить все элементы формы с формой «горизонтально-горизонтальной формы» твитер-бутстрапа и значком звездочки для обязательных полей (необходимо установить в атрибуте inputfilter, а не атрибуте элемента)

FormControlGroup.php (ViewHelper для визуализации форма элемента как)

<?php 

namespace Application\View\Helper; 

use Zend\InputFilter\InputFilter; 

use Zend\Form\ElementInterface; 
use Zend\Form\Element; 
use Zend\Form\Fieldset; 

use Zend\Form\View\Helper\AbstractHelper; 
use Zend\Form\View\Helper\FormLabel; 
use Zend\Form\View\Helper\FormElement; 
use Zend\Form\View\Helper\FormElementErrors; 

use Application\View\Helper\FormControlGroupFieldset; 

use Zend\Debug\Debug; 

class FormControlGroup extends AbstractHelper 
{ 

public function __invoke(ElementInterface $elem = null,InputFilter $inputFilter = null){ 
    if(!$elem){ return $this; } 

    // back up for fieldsets 
    if($elem instanceof Fieldset){ 
     if($this->getView()){ 
      $fcgf = new FormControlGroupFieldset(); 
      $fcgf->setView($this->getView()); 
      return $fcgf->__invoke($elem,$inputFilter); 
     } else { 
      throw new Exception\DomainException(sprintf('FormControlGroup ViewHelper expects either an Element or a Fieldset. No View Could be found in the provided Object.')); 
     } 
    } 

    // add control-group container 
    $out = '<div class="control-group">'; 

    // add control-label class to label if label exists 
    $out .= $this->renderLabel($elem,$inputFilter); 

    // add controls container 
    $out .= '<div class="controls">'; 

    // ensure renderer for used viewhelpers 
    if($this->getView()){ 
     // render element 
     $el = new FormElement(); 
     $el->setView($this->getView()); 
     $out .= $el->__invoke($elem); 
     unset($el); 

     // render element errors 
     $er = new FormElementErrors(); 
     $er->setView($this->getView()); 
     $out .= $er->__invoke($elem,array('class' => 'help-inline')); 
     unset($er); 
    } else { 
     $out .= 'No renderer found'; 
    } 


    // close containers 
    $out .= '</div></div>'; 
    return $out; 
} 

/** 
* 
* @param ElementInterface $elem 
* @return string rendered Label with control-label class 
*/ 
protected function renderLabel(ElementInterface &$elem,InputFilter &$inputFilter = null){ 
     if($elem->getLabel()){ 
     $lblAttr = $elem->getLabelAttributes(); 
     if($lblAttr && key_exists('class', $lblAttr)){ 
      if(stripos($lblAttr['class'],'control-label')){ 
       $lblAttr['class'] .= 'control-label'; 
      } 
     } else { 
      $lblAttr['class'] = 'control-label'; 
     } 
     $elem->setLabelAttributes($lblAttr); 
     // check whether this element is required to fill out 
     if($inputFilter){ 
      $inputs = $inputFilter->getInputs(); 
      if(key_exists($this->getRealElementName($elem),$inputs)){ 
       if($inputs[$this->getRealElementName($elem)]->isRequired()){ 
        $elem->setLabel($elem->getLabel().'<i class="icon-asterisk"></i>'); 
       } 
      } 
     } 
     $lbl = new FormLabel(); 
     return $lbl->__invoke($elem); 
    } else { 
     return ''; 
    } 
} 

public function getRealElementName($e){ 
    $start = strrpos($e->getName(), '[')+1; 
    $end = strpos($e->getName(),']'); 
    $elName = substr($e->getName(),$start,$end-$start); 
    return $elName; 
} 
} 

FormControlGroupFieldset.php (ViewHelper для визуализации полей формы в качестве - вызывается FormControlGroupFieldset)

<?php 

namespace Application\View\Helper; 


use Zend\InputFilter\InputFilter; 

use Zend\Form\Fieldset; 
use Zend\Form\View\Helper\AbstractHelper; 

use Application\View\Helper\FormControlGroup; 

use Zend\Debug\Debug; 


class FormControlGroupFieldset extends AbstractHelper 
{ 

public function __invoke(Fieldset $fs=null,InputFilter $inputFilter = null){ 
    if(!$fs){ return $this; } 

    $out = '<fieldset>'; 

    if($fs->getLabel()){ 
     $out .= '<legend>'.$fs->getLabel().'</legend>'; 
    } 

    if($this->getView() && sizeof($fs->getElements()) > 0){ 
     $cg = new FormControlGroup(); 
     $cg->setView($this->getView()); 
     if($inputFilter){ 
      $inputs = $inputFilter->getInputs(); 
      $fsInput = $inputs[$fs->getName()]; 
     } 
     foreach($fs->getElements() as $e){ 
      $out .= $cg->__invoke($e,$fsInput); 
     } 
     unset($cg); 
    } else { 
     $out .= "No Fieldset renderer found."; 
    } 

    $out .= '</fieldset>'; 

    return $out; 
} 

public function getRealElementName($e){ 
    $start = strrpos($e->getName(), '[')+1; 
    $end = strpos($e->getName(),']'); 
    $elName = substr($e->getName(),$start,$end-$start); 
    return $elName; 
} 

} 

Вы, возможно, потребуется настроить пространство имен ...

1

Используя принципы, предоставляемые Сэм, мне удалось уладить это следующим образом:

Я создал Application/src/Application/Form/View/Helper/RequiredMarkInFormLabel.php файл:

<?php 
namespace Application\Form\View\Helper; 

use Zend\Form\View\Helper\FormLabel as OriginalFormLabel; 
use Zend\Form\ElementInterface; 
use Zend\Form\Exception; 

class RequiredMarkInFormLabel extends OriginalFormLabel 
{ 
    public function __invoke(ElementInterface $element = null, $labelContent = null, $position = null) 
    { 

     ... 

     // Set $required to a default of true | existing elements required-value 
     $required = ($element->hasAttribute('required') ? true : false); 

     if (true === $required) { 
      $labelContent = sprintf(
       '%s<span class="required-mark">*</span>', 
       $labelContent 
      ); 
     } 

     return $openTag . $labelContent . $this->closeTag(); 
    } 
} 

Что я включен путем добавления этого кода в Application/Module.php:

public function getViewHelperConfig() 
{ 
    return array(
     'invokables' => array(
      'formlabel' => 'Application\Form\View\Helper\RequiredMarkInFormLabel', 
     ), 
    ); 
} 

Надеюсь, это будет полезно кому-то! ;)

1

Я сделал динамическое добавление требуемого атрибута на Элементы на основе InputFilter.

На моем FormHelper:

public function render(Traversable $fieldset) 
    { 
     ... 
     elseif ($element instanceof ElementInterface) { 
       if ($fieldset instanceof \Zend\InputFilter\InputFilterProviderInterface){ 
        $ifs = $fieldset->getInputFilterSpecification(); 
        $start = strrpos($element->getName(), '[')+1; 
        $end = strpos($element->getName(),']'); 
        $elementName = substr($element->getName(),$start,$end-$start); 
        if (isset($ifs[$elementName]['required'])){ 
         $element->setAttribute('required', $ifs[$elementName]['required']); 
        } 

       } 
       $form .= $elementHelper->render($element); 
     ... 

     return $form; 
    } 

На ElementHelper

public function render(ElementInterface $element){ 
... 
$required = ($element->hasAttribute('required') ? $element->getAttribute('required') : false); 
... 
if (true === $required && ($label != '' || $label != null || $label != false)) { 
    $label .= '*'; 
} 

Таким образом, вам не нужно беспокоиться, чтобы добавить атрибут и InputSpecification, предложенный

@ Сэм
2

Хотя ответы Сэма и Целлюлозы - очень приятное решение.

Я обеспокоен тем, что они не будут масштабируемыми по мере продвижения каркаса ZF2. Несмотря на то, что они расширяют Zend \ Form \ View \ Helper \ FormLabel, существует много кода в повторяющемся методе __invoke. Поскольку изменения внесены в структуру и исходный помощник, нам придется постоянно обновлять ваш новый помощник формы, чтобы дублировать любые изменения в исходном методе __invoke.

Более простым решением было бы вызвать родительский :: __ invoke() с предоставленными аргументами в ViewHelper, чтобы избежать дублирования кода.

Итак, вот решение:

Создание ViewHelper в Application/SRC/Application/Форма/View/Helper/RequiredMarkInFormLabel.php

<?php 
namespace Application\Form\View\Helper; 

use Zend\Form\View\Helper\FormLabel as OriginalFormLabel; 
use Zend\Form\ElementInterface; 

/** 
* Add mark (*) for all required elements inside a form. 
*/ 
class RequiredMarkInFormLabel extends OriginalFormLabel 
{ 
    /** 
    * Invokable 
    * 
    * @return str 
    */  
    public function __invoke(ElementInterface $element = null, $labelContent = null, $position = null) 
    { 

     // invoke parent and get form label 
     $originalformLabel = parent::__invoke($element,$labelContent,$position); 

     // check if element is required 
     if ($element->hasAttribute('required')) { 
      // add a start to required elements 
      return '<span class="required-mark">*</span>' . $originalformLabel; 
     }else{ 
      // not start to optional elements 
      return $originalformLabel; 
     } 
    } 
} 

Не забудьте зарегистрировать ViewHelper в заявке/конфигурации /module.config.php

'view_helpers' => array(
    'invokables'=> array(
     'formlabel' => 'Application\Form\View\Helper\RequiredMarkInFormLabel' 
    ) 
), 
+0

Это важное соображение и чистое решение этой проблемы. Очень хорошо! – lorey

0

для кого-то еще интересно ... Существует простое решение, использование CSS: после того, как псевдо-класса для добавления «*» на этикетку.

label.required:after{ 
    content:'*'; 
} 

Это не может быть проще!

Смежные вопросы