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


Я знаю, что могу удалить лишнее вещество из каждого элемента по отдельности, как это

$button ->removeDecorator('DtDdWrapper')
        ->removeDecorator('HtmlTag')
     ->removeDecorator('Label');
Мне было интересно, могу ли я достичь того же для всех моих элементов в форме zend?
И как можно удалить dl, обертывающий форму?
7 10

7 ответов:

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

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

Вы можете отключить декораторы на уровне формы, как это.

$form->setElementDecorators($decorators);

Это удалит декораторы по умолчанию и установит декораторы в массиве $decorators в качестве декораторов. Если вы хотите выборочно удалить декораторы, вам следует изучить реализацию этого метода и создать аналогичный для удаления декораторов.

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

Следующие 4 строки кода работают для меня

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

Прекрасный

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

Немного запоздал в потоке, но это сработало для меня

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

Попробуйте это:

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

Или

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

Используйте это:

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