2

我使用以下代码将电子邮件元素添加到我的 Zend Framework 2 表单中:

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

默认情况下,此元素的 getInputSpecification() 方法将 required 设置为 true。但是元素对象不包含任何必需的属性,因此标记也不包含。

如何为我的表单添加标记以便我的 CSS 能够添加所需的后缀?或者至少:自定义视图助手如何获取“必需”设置?

我意识到我可以只添加一个必需的属性,但这感觉不对,因为它可能与内部元素的“必需”设置不同步。

4

6 回答 6

3

尽管 Sam 和 Cellulosa 的反应是一个非常好的解决方案。

我担心随着 ZF2 框架的发展,这些将无法扩展。尽管他们正在扩展 Zend\Form\View\Helper\FormLabel,但 __invoke 方法中有很多重复的代码。随着对框架和原始助手的更改,我们将不得不不断更新您的新表单视图助手以复制原始 __invoke 方法中的任何更改。

一个更简单的解决方案是使用提供的参数将 parent::__invoke() 调用到 ViewHelper 中,以避免重复代码。

所以,这里是解决方案:

在 Application/src/Application/Form/View/Helper/RequiredMarkInFormLabel.php 创建 ViewHelper

<?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;
        }
    }
}

记得在 Application/config/module.config.php 注册 ViewHelper

'view_helpers' => array(
    'invokables'=> array(
        'formlabel' => 'Application\Form\View\Helper\RequiredMarkInFormLabel'  
    )
),  
于 2014-01-14T16:25:13.617 回答
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();
}

记得像这样注册你自己ViewHelperModule#getViewHelperConfig()

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

我实际上有点惊讶这样的事情没有实现,尽管我确信这是有原因的:)

于 2013-04-28T08:10:19.807 回答
1

使用 Sam 提供的指南,我设法将其排序如下:

我创建了一个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',
        ),
    );
}

希望这对某人有帮助!;)

于 2013-08-20T12:45:16.843 回答
1

我所做的是根据 InputFilter 在 Elements 上动态添加所需的属性。

在我的表单助手上:

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;
    }

在元素助手上

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

因此,您不必担心按照@Sam 的建议添加属性和 InputSpecification

于 2013-12-26T16:51:47.183 回答
0

对于其他想知道的人......有一个简单的解决方案,使用 css :after 伪类将 '*' 附加到标签。

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

不能比这更简单!

于 2014-09-16T08:14:53.080 回答
0

好的,所以我厌倦了进一步寻找......因此我只是解析了元素名以查找括号之间最深的字符串......这是我的视图助手,用于使用“form-horizo​​ntal”表单布局呈现表单的所有元素twitter bootstrap 和必填字段的星号图标(需要在 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;
}

}

您可能需要调整命名空间...

于 2013-05-17T17:18:48.683 回答