【问题标题】:Zend Framework 2 form element error-class + custom ViewHelper to render formZend Framework 2 表单元素错误类 + 自定义 ViewHelper 来呈现表单
【发布时间】:2013-12-29 21:37:45
【问题描述】:

这是我本周(和整体)的第三个问题 - 希望我不会在这里被禁止:D 无论如何,四处搜索并找不到解决我问题的确切解释。

A.我四处搜索并找到了一个自定义 ViewHelper 来呈现我的表单。它所做的是递归地获取所有字段集,当它到达元素级别时,它是这样的:

    public function renderElement($element) {
        $html = '
            <div class="row">' . 
            '<label class="col-md-12" for="' . $element->getAttribute('id') . '">' . $element->getLabel() . '</label>' . 
            $this->view->formElement($element) . 
            $this->view->FormElementErrors($element) .
            '<div class="clearfix" style="height: 15px;"></div>';

        return $html . PHP_EOL;
    }

表单渲染正常,除了: 1)如何向表单元素添加错误类? (例如,如果我在视图中使用 formRow 助手,它会自动广告一个“输入错误”类,同时在创建元素时还保留在我的字段集中指定的初始类 - 'attributes' => array('class' => ' some-class')),因此元素的 class 属性变为“some-class input-error”,以防它无效。 2) 如何为包含错误消息的“ul”设置一个类(由 $this->view->FormElementErrors($element) 呈现的“ul”)?希望这是一个单行的,我不必逐个消息并为错误消息列表编写html,但如果不是这样(我也不知道该怎么做)。

B.假设有时我不使用这个自定义 ViewHelper 来呈现我的表单。 Zend 的 formRow 视图助手有时会很方便。在我看来,这使我想到了以下代码:

    echo $this->formRow($this->form->get('user_fieldset')->get('user_name'));

我注意到这会自动在我的元素上添加“输入错误”类(以防它无效),这是完美的,但是我怎么能告诉 formRow 为显示错误消息的“ul”提供一个类?

我会走得更远,问我怎样才能把它变成这样:

    echo $this->formLabel($this->form->get('user_fieldset')->get('user_name'));
    echo $this->formInput($this->form->get('user_fieldset')->get('user_name'));
    echo $this->formElementErrors($this->form->get('user_fieldset')->get('user_name'), array('class' => 'form-validation-error'));

到向元素广告错误类的东西中,不仅仅是向错误消息列表,但如果有人回答 A 点,我认为这是同一个问题。

【问题讨论】:

  • 你需要为
      元素设置类吗?
  • 我需要为该 ul 设置一个类,以便使用 css 对其进行样式设置。我不想从表单的类(.frm-class ul)或表单id级联,我想直接通过ul的属性来做。

标签: forms zend-framework2 custom-component viewhelper


【解决方案1】:

我已经设法做到了:

public function renderElement($element) {
    // FORM ROW
    $html = '<div class="form-group">';

    // LABEL
    $html .= '<label class="form-label" for="' . $element->getAttribute('id') . '">' . $element->getLabel() . '</label>';

    // ELEMENT
    /*
     - Check if element has error messages
     - If it does, add my error-class to the element's existing one(s),
       to style the element differently on error
    */
    if (count($element->getMessages()) > 0) {
        $classAttribute = ($element->hasAttribute('class') ? $element->getAttribute('class') . ' ' : '');
        $classAttribute .= 'input-error';
        /* 
         * Normally, here I would have added a space in my string (' input-error')
         * Logically, I would figure that if the element already has a class "cls"
         * and I would do $element->getAttribute('class') . 'another-class'
         * then the class attribute would become "clsanother-class"
         * BUT it seems that, even if I don't intentionally add a space in my string,
         * I still get "cls another-class" as the resulted concatenated string
         * I assume that when building the form, ZF2 automatically
         * adds spaces after attributes values? so you/it won't have to
         * consider that later, when you'd eventually need to add another
         * value to an attribute?
         */
        $element->setAttribute('class', $classAttribute);
    }
    $html .= $this->view->formElement($element);
    /*
     * Of course, you could decide/need to do things differently,
     * depending on the element's type

       switch ($element->getAttribute('type')) {
           case 'text':
           case 'email': {

               break;
           }
           default: {

           }
       }
     */
    // ERROR MESSAGES
    // Custom class (.form-validation-error) for the default html wrapper - <ul>
    $html .= $this->view->FormElementErrors($element, array('class' => 'form-validation-error'));

    $html .= '</div>'; # /.form-group
    $html .= '<div class="clearfix" style="height: 15px;"></div>';

    return $html . PHP_EOL;
}

我不喜欢这个,但我想没有更短的方法。我认为 ZF2 应该有这样的东西:

if ($element->hasErrors()) { $element->addClass('some-class'); }

开箱即用。这就是我所期望的答案,它只是我错过/找不到的一种方法。但事实证明,ZF2 在整个世界中并没有您开箱即用可能需要的任何东西,您最终不得不(或多或少)编写偶尔的助手。

无论如何,如果有人需要它,这里是整个 RenderForm 视图助手:

namespace User\View\Helper;

use Zend\View\Helper\AbstractHelper;

class RenderForm extends AbstractHelper {

    public function __invoke($form) {
        $form->prepare();
        $html = $this->view->form()->openTag($form) . PHP_EOL;
        $html .= $this->renderFieldsets($form->getFieldsets());
        $html .= $this->renderElements($form->getElements());
        $html .= $this->view->form()->closeTag($form) . PHP_EOL;
        return $html;
    }

    public function renderFieldsets($fieldsets) {

        foreach ($fieldsets as $fieldset) {
            if (count($fieldset->getFieldsets()) > 0) {
                $html = $this->renderFieldsets($fieldset->getFieldsets());
            } else {
                $html = '<fieldset>';
                    // You can use fieldset's name for the legend (if that's not inappropriate)
                    $html .= '<legend>' . ucfirst($fieldset->getName()) . '</legend>';
                    // or it's label (if you had set one)
                    // $html .= '<legend>' . ucfirst($fieldset->getLabel()) . '</legend>';
                    $html .= $this->renderElements($fieldset->getElements());
                $html .= '</fieldset>';
                // I actually never use the <fieldset> html tag.
                // Feel free to use anything you like, if you do have to
                // make grouping certain elements stand out to the user
            }
        }

        return $html;
    }

    public function renderElements($elements) {
        $html = '';
        foreach ($elements as $element) {
            $html .= $this->renderElement($element);
        }
        return $html;
    }

    public function renderElement($element) {
        // FORM ROW
        $html = '<div class="form-group">';

        // LABEL
        $html .= '<label class="form-label" for="' . $element->getAttribute('id') . '">' . $element->getLabel() . '</label>'; # add translation here

        // ELEMENT
        /*
         - Check if element has error messages
         - If it does, add my error-class to the element's existing one(s),
           to style the element differently on error
        */
        if (count($element->getMessages()) > 0) {
            $classAttribute = ($element->hasAttribute('class') ? $element->getAttribute('class') . ' ' : '');
            $classAttribute .= 'input-error';

            $element->setAttribute('class', $classAttribute);
        }
        $html .= $this->view->formElement($element);

        // ERROR MESSAGES
        $html .= $this->view->FormElementErrors($element, array('class' => 'form-validation-error'));


        $html .= '</div>'; # /.row
        $html .= '<div class="clearfix" style="height: 15px;"></div>';

        return $html . PHP_EOL;
    }

}

用户是我的模块。我在它的配置文件夹中创建了一个“viewhelper.config.php”:

return array(
    'invokables' => array(
        'renderForm' => 'User\View\Helper\RenderForm',
    ),
);

在 Module.php 中:

public function getViewHelperConfig() {
    return include __DIR__ . '/config/viewhelper.config.php';
}

然后,在您看来,只需调用:

$this->renderForm($form);

当然,如果你没有很多视图助手,你不能为此创建一个单独的配置文件,留下 Module.php 并简单地添加:

'view_helpers' => array(
    'invokables' => array(
        'renderForm' => 'User\View\Helper\RenderForm',
    ),
),

到任何配置文件。

【讨论】:

    【解决方案2】:

    我使用 getMessages() 方法来检查元素是否有验证消息。例如。

    <div class="form-group <?=($this->form->get('user_fieldset')->get('user_name')->getMessages())?'has-error':'';?>">
        ...
    </div>
    

    这个问题似乎很老了,你一定是自己解决的。 :)

    【讨论】:

      猜你喜欢
      • 2012-09-04
      • 1970-01-01
      • 2012-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-08
      • 1970-01-01
      相关资源
      最近更新 更多