Как удалить все DtDdWrappers и ярлыки на элементы формы Zend

Я знаю, что я могу удалить лишний материал из каждого элемента отдельно так

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

Мне было интересно, могу ли я сделать то же самое для всех моих элементов в форме zend?
И как удалить dl-оболочку формы?

Ответ 1

Маркус, вот решение, которое я использую, похоже, работает хорошо, надеюсь, он будет вам подходит.

Во-первых, чтобы отобразить форму без тега <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 на любой тэг, который вы используете, я обычно использую div класса form, который мы увидим позже.

Затем необходимо обработать элементы. Элементы Zend_Form имеют разные декораторы для разных типов элементов. Следующие группы типов элементов имеют свой собственный набор декораторов: [Submit и Button], [Captcha], [File], [Image] и [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'))
);

Это обернет каждый элемент формы в тег div классом form-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- > 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 в качестве декораторов. Если вы хотите выборочно удалить декораторы, вы должны изучить реализацию этого метода и создать аналогичный для удаления декораторов.

Если вы хотите отключить некоторые декораторы для всех ваших форм, создайте класс Your_Form, который расширяет Zend_Form и удаляет эти декораторы на Your_Form и расширяет все ваши формы из этого класса или просто создает экземпляры этого класса.

Ответ 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, в разметке формы по умолчанию не должно быть тегов, кроме тегов <form>, <input> и <label>. Все остальное может быть добавлено разработчиком с помощью существующих методов.

Ответ 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');
    }