2

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

答:我四处搜索并找到了一个自定义 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')),因此元素的类属性变为“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'));

也可以将错误类添加到元素中,而不仅仅是错误消息列表,而且如果有人回答指向 AI 认为这是同一个问题。

4

2 回答 2

4

I've managed to do it like this:

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

I'm not to fond of this, but I suppose there is no shorter way. I thought ZF2 shoud have something like:

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

right out of the box. That's the answer I would have expected, that it would simply be a method I missed/couldn't find. But it turns out that ZF2 doesn't have quite anything in the whole world that you might need right out of the box, you end up having to write the (more or less) occasional helpers.

Anyway, if someone ever needs it here's the entire RenderForm view helper:

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

}

User is my module. I've created a 'viewhelper.config.php' in it's config folder:

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

and in Module.php:

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

Then, in your view simply call:

$this->renderForm($form);

Of course, if you don't have many view helpers, you could not create a separate config file just for that, leave Module.php alone and simply add:

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

to any configuration file.

于 2013-12-31T14:03:15.683 回答
2

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

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

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

于 2015-01-04T17:49:35.270 回答