如何删除Zend表单元素上的所有DtDdWrappers和标签

时间:2010-11-16 04:25:01

标签: php zend-framework zend-form

我知道我可以像这样单独删除每个元素中的额外内容

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

我想知道我是否可以以zend形式为我的所有元素实现相同的目标? 如何删除包裹表单的dl?

7 个答案:

答案 0 :(得分:25)

马库斯,这是我使用的解决方案似乎运作良好,希望它适合你。

首先,为了呈现没有<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更改为您使用的任何标记,我通常使用divform,我们稍后会看到

接下来,需要处理这些元素。 Zend_Form元素具有不同类型元素的不同装饰器。以下元素类型组各自具有各自独特的装饰器集:[Submit&amp;按钮],[验证码],[文件],[图像]和[收音机*]。无线电装饰器与标准元素非常相似,只是它没有在标签内指定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自动将正确的装饰器分配给特定的元素类型(您可以将它们分配给特定的元素名称),但我们可以设置默认值,并让自己轻松访问来自一个地方的装饰者,所以如果他们需要改变,他们可以很容易地改变所有形式。

这是基类:

<?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-&gt; 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
);

随意请求澄清任何事情,希望这会帮助你。

答案 1 :(得分:4)

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

$form->setElementDecorators($decorators);

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

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

答案 2 :(得分:2)

以下4行代码适用于我

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

可爱

答案 3 :(得分:2)

我认为这样做的唯一方法是扩展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的许多其他开发人员,除了<form><input><label>标签之外,默认情况下表单标记中不应包含任何标记。开发人员可以使用现有方法添加任何其他内容。

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

试试这个:

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

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

答案 6 :(得分:0)

使用此:

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