【问题标题】:How To Remove All DtDdWrappers and Labels on Zend Form Elements如何删除 Zend 表单元素上的所有 DtDdWrapper 和标签
【发布时间】:2011-05-10 15:00:09
【问题描述】:

我知道我可以像这样从每个元素中单独删除多余的东西

$button ->removeDecorator('DtDdWrapper')
        ->removeDecorator('HtmlTag')
     ->removeDecorator('Label');

我想知道是否可以对 zend 表单中的所有元素实现相同的效果?
以及如何删除包裹表单的 dl?

【问题讨论】:

  • 我在你的问题上花了 250 rep 之后,也许你可以接受 draw010 给出的处理答案!

标签: php zend-framework zend-form


【解决方案1】:

Markus,这是我使用的一个似乎效果不错的解决方案,希望它适合你。

首先,为了呈现没有<dl> 标签的表单,我们需要在表单对象本身上设置装饰器。在扩展 Zend_Form 的类内部,您可以调用 Zend_Form->setDecorators() 并传递一个表单装饰器数组。

来自参考指南:

The default decorators for Zend_Form are FormElements, HtmlTag (wraps in a definition list), and Form; the equivalent code for creating them is as follows:

  $form->setDecorators(array(
      'FormElements',
      array('HtmlTag', array('tag' => 'dl')),
      'Form'
  ));

要将表单包装在 dl 以外的其他东西中,我们使用上述装饰器,但将 dl 更改为您使用的任何标签,我通常使用 form 类的 div,我们稍后会看到。

接下来,需要处理元素。 Zend_Form 元素对不同类型的元素有不同的装饰器。以下每组元素类型都有自己独特的一组装饰器:[Submit & Button]、[Captcha]、[File]、[Image] 和 [Radio*]。 radio 的装饰器与标准元素非常相似,只是它没有在标签内指定for 属性。

所有其他表单元素、文本、密码、选择、复选框等都使用同一组默认装饰器。

要从单个表单元素中删除 dd/dt 标签,我们需要对其应用我们自己的一组装饰器。下面是一个不使用 dd/dt 标签的例子:

array(
    'ViewHelper',
    'Errors',
    array('Description', array('tag' => 'p', 'class' => 'description')),
    array('HtmlTag',     array('class' => 'form-div')),
    array('Label',       array('class' => 'form-label'))
);

这会将每个表单元素包装在一个带有form-div 类的div 标记中。问题是,您必须将这组装饰器应用于您不想被包装在 dd/dt 标签中的每个元素,这可能有点问题。

为了解决这个问题,我创建了一个从 Zend_Form 扩展的类,并为其提供一些默认行为和与 Zend_Form 的默认装饰器不同的装饰器。

虽然我们不能让 Zend_Form 自动将正确的装饰器分配给特定的元素类型(您可以将它们分配给特定的元素 names),但我们可以设置一个默认值,让自己轻松访问装饰器来自一个地方,因此如果需要更改,可以轻松更改所有表单。

这是基类:

<?php

class Application_Form_Base extends Zend_Form
{
    /** @var array Decorators to use for standard form elements */
    // these will be applied to our text, password, select, checkbox and radio elements by default
    public $elementDecorators = array(
        'ViewHelper',
        'Errors',
        array('Description', array('tag' => 'p', 'class' => 'description')),
        array('HtmlTag',     array('class' => 'form-div')),
        array('Label',       array('class' => 'form-label', 'requiredSuffix' => '*'))
    );

    /** @var array Decorators for File input elements */
    // these will be used for file elements
    public $fileDecorators = array(
        'File',
        'Errors',
        array('Description', array('tag' => 'p', 'class' => 'description')),
        array('HtmlTag',     array('class' => 'form-div')),
        array('Label',       array('class' => 'form-label', 'requiredSuffix' => '*'))
    );

    /** @var array Decorator to use for standard for elements except do not wrap in HtmlTag */
    // this array gets set up in the constructor 
    // this can be used if you do not want an element wrapped in a div tag at all
    public $elementDecoratorsNoTag = array();

    /** @var array Decorators for button and submit elements */
    // decorators that will be used for submit and button elements
    public $buttonDecorators = array(
        'ViewHelper',
        array('HtmlTag', array('tag' => 'div', 'class' => 'form-button'))
    );


    public function __construct()
    {
        // first set up the $elementDecoratorsNoTag decorator, this is a copy of our regular element decorators, but do not get wrapped in a div tag
        foreach($this->elementDecorators as $decorator) {
            if (is_array($decorator) && $decorator[0] == 'HtmlTag') {
                continue; // skip copying this value to the decorator
            }
            $this->elementDecoratorsNoTag[] = $decorator;
        }

        // set the decorator for the form itself, this wraps the <form> elements in a div tag instead of a dl tag 
        $this->setDecorators(array(
                             'FormElements',
                             array('HtmlTag', array('tag' => 'div', 'class' => 'form')),
                             'Form'));

        // set the default decorators to our element decorators, any elements added to the form
        // will use these decorators
        $this->setElementDecorators($this->elementDecorators);

        parent::__construct();
        // parent::__construct must be called last because it calls $form->init()
        // and anything after it is not executed
    }
}

/*
   Zend_Form_Element default decorators:
   $this->addDecorator('ViewHelper')
        ->addDecorator('Errors')
        ->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
        ->addDecorator('HtmlTag', array('tag' => 'dd',
                                        'id'  => array('callback' => $getId)))
        ->addDecorator('Label', array('tag' => 'dt'));
*/

现在要使用这个类,从这个基类扩展你的所有表单,然后像往常一样分配元素。如果您使用Zend_Form_Element_XXX 而不是addElement(),那么您需要将装饰器之一作为选项传递给元素构造函数,如果您使用 Zend_Form->addElement,那么它将使用我们分配的默认装饰器$elementDecorators在课堂上。

这是一个展示如何从该类扩展的示例:

<?php

class Application_Form_Test extends Application_Form_Base
{
    public function init()
    {
        // Add a text element, this will automatically use Application_Form_Base->elementDecorators for its decorators
        $this->addElement('text', 'username', array(
            'label'      => 'User Name:',
            'required'   => false,
            'filters'    => array('StringTrim'),
        ));

        // This will not use the correct decorators unless we specify them directly
        $text2 = new Zend_Form_Element_Text(
            'text2',
            array(
                'decorators' => $this->elementDecorators, // must give the right decorator
                'label' => 'Text 2'
            )
        );

        $this->addElement($text2);

        // add another element, this also uses $elementDecorators
        $this->addElement('text', 'email', array(
            'label'      => 'Email:', 
            'required'   => false,
            'filters'    => array('StringTrim', 'StringToLower'), 
        ));

        // add a submit button, we don't want to use $elementDecorators, so pass the button decorators instead
        $this->addElement('submit', 'submit', array(
            'label' => 'Continue', 
            'decorators' => $this->buttonDecorators // specify the button decorators
        ));
    }
}

这显示了一种非常有效的方法来摆脱 dd/dt 和 dl 元素并用您自己的元素替换它们。必须为每个元素指定装饰器有点不方便,而不是能够将装饰器分配给特定元素,但这似乎运作良好。

要添加一个我认为您想要做的解决方案,如果您想渲染一个没有标签的元素,只需创建一个新的装饰器并从中省略标签装饰器,如下所示:

$elementDecorators = array(
    'ViewHelper',
    'Errors',
    array('Description', array('tag' => 'p', 'class' => 'description')),
    array('HtmlTag',     array('class' => 'form-div')),
    // array('Label',       array('class' => 'form-label', 'requiredSuffix' => '*'))
    // comment out or remove the Label decorator from the element in question
    // you can do the same for any of the decorators if you don't want them rendered
);

如有任何问题,请随时要求澄清,希望这会对您有所帮助。

【讨论】:

  • 非常感谢您为此付出的努力!很好的答案!
【解决方案2】:

您可以像这样在表单级别禁用装饰器。

$form->setElementDecorators($decorators);

这将删除默认装饰器并将$decorators数组中的装饰器设置为装饰器。如果您想有选择地移除装饰器,您应该研究此方法的实现并创建一个类似的用于移除装饰器的方法。

如果您想为所有表单禁用某些装饰器,请创建一个扩展 Zend_Form 的类 Your_Form 并删除 Your_Form 上的那些装饰器并从此类扩展您的所有表单,或者只是创建此类的实例。

【讨论】:

  • 也可以使用setDisableLoadDefaultDecorators()来禁用加载默认装饰器
  • @Gordon 这不会删除所有标签。
  • 这个答案不能解决表单本身的包装问题!此外,必须有一个解决方案,只允许删除所有装饰器而不设置任何自定义装饰器。
  • @markus setDecorators()Zend_Form 上的一种方法,它将覆盖任何现有的装饰器,所以我不确定您为什么认为我的回答不能解决问题。传递一个空数组,表单本身的所有装饰器都消失了。
  • @Gordon:我仍然得到 dl、dt 和 dd 标签。我真的没有为此投入 250 个代表,因为它有效。我可能做错了什么,但多年来我一直在尝试不同的东西,但到目前为止我从未设法得到一个干净的表格。如果我必须调用 2 个以上的方法来获得一个干净的表单,那么 Zend_Form 就会出现严重问题。我没有时间对此进行调查,它必须起作用,所以我希望有人想要 250 个代表并提出一个完整且可行的解决方案。
【解决方案3】:

以下 4 行代码对我有用

$elements = $this->getElements();
        foreach($elements as $element) {
            $element->removeDecorator('DtDdWrapper')
            ->removeDecorator('HtmlTag')
            ->removeDecorator('Label');
        }

可爱

【讨论】:

  • 这个答案不能解决表单本身的包装问题!此外,这将删除必要的标签文本。
【解决方案4】:

我认为这样做的唯一方法是扩展 Zend_Form 然后覆盖 loadDefaultDecorators() 和 render() 函数,如下所示。看看这是否适合你。

class App_Form extends Zend_Form
{
    public function loadDefaultDecorators() 
    {
        if ($this->loadDefaultDecoratorsIsDisabled()) {
            return $this;
        }

        $decorators = $this->getDecorators();
        if (empty($decorators)) {
            $this->addDecorator('FormElements')
                 ->addDecorator('Form');
        }
        return $this;
    }

    public function render(Zend_View_Interface $view = null) 
    {
        $elements = $this->getElements();
        foreach($elements as $element){
            $element->setDecorators(array(
                'ViewHelper',
                'Errors',
                array('Description', array('tag' => 'p', 'class' => 'description')),
                'Label',
            ));
        }
        $content = parent::render($view);
        return $content;
    }
}

编辑:

我认为这种方法仍然会有些不便,因为新的 render() 函数会删除您添加到元素中的所有标签。为了解决这个问题,您需要扩展 Zend_Form_Element 并覆盖它的 loadDefaultDecorators() 方法,就像我在这里为表单所做的那样。

在我看来,以及可能许多其他使用 Zend_Form 的开发人员的意见,默认情况下,除了&lt;form&gt;&lt;input&gt;&lt;label&gt; 标签之外,表单标记中不应该有任何标签。开发人员可以使用现有方法添加任何其他内容。

【讨论】:

    【解决方案5】:

    在线程中有点晚了,但它对我有用

    foreach( $this->getElements() as $el )
    {
        foreach( $el->getDecorators() as $dec )
        {
            if( $dec instanceof Zend_Form_Decorator_HtmlTag ||
                $dec instanceof Zend_Form_Decorator_Label )
            {
                $dec->setOption( 'tag', 'li' );
            };
        };
    };
    

    【讨论】:

      【解决方案6】:

      试试这个:

      foreach ($form->getElements() as $element) {
          $element->removeDecorator('DtDdWrapper')
              ->removeDecorator('HtmlTag')
              ->removeDecorator('Label');
      }
      

      foreach ($form->getElements() as $element) {
          $element->clearDecorators();
      }
      

      【讨论】:

        【解决方案7】:

        使用这个:

            foreach ($this->getElements() as $element) {
                $decorator = $element->getDecorator('label');
                if (!$decorator) {
                    continue;
                }
                $decorator->removeOption('tag');
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-18
          • 2015-09-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-25
          • 1970-01-01
          相关资源
          最近更新 更多