我使用以下代码将电子邮件元素添加到Zend Framework 2表单中:
$form->add(array(
'type' => 'Zend\Form\Element\Email',
'name' => 'email',
'options' => array(
'label' => 'Email'
),
));
默认情况下,此元素的getInputSpecification()方法设置为true。但是元素对象不包含任何必需的属性,因此标记也不包含。
如何为我的css添加标记以便能够添加所需的后缀?或者至少:自定义视图帮助器如何获取“必需”设置?
我意识到我可以添加一个必需的属性,但感觉不对,因为它可能与内部元素'required'设置不同步。
答案 0 :(得分: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;
},
),
);
}
我真的有点惊讶这样的事情没有实现,虽然我确定这是有原因的:)
答案 1 :(得分:2)
虽然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'
)
),
答案 2 :(得分: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',
),
);
}
希望这会对某人有所帮助! ;)
答案 3 :(得分: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 .= '*';
}
因此,您不必担心按@Sam
的建议添加属性和InputSpecification答案 4 :(得分:0)
好的,所以我厌倦了进一步寻找......因此我只是解析了元素名称以寻找括号中最深的字符串....这里是我的追踪器,用#&#39;来渲染表单的所有元素。形式水平&#39; 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;
}
}
您可能需要调整命名空间......
答案 5 :(得分:0)
对于其他任何想知道的人...有一个简单的解决方案,使用css:在伪类之后将'*'附加到标签上。
label.required:after{
content:'*';
}
这不可能比那简单!