Как удалить все DtDdWrappers и метки на элементах Zend Form - PullRequest
10 голосов
/ 16 ноября 2010

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

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

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

Ответы [ 7 ]

25 голосов
/ 05 октября 2011

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

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

Не стесняйтесь просить разъяснений по любому вопросу, надеюсьэто поможет вам.

4 голосов
/ 16 ноября 2010

Вы можете отключить декораторы на уровне формы следующим образом.

$form->setElementDecorators($decorators);

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

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

2 голосов
/ 07 октября 2011

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

2 голосов
/ 10 февраля 2011

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

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

симпатичный

1 голос
/ 15 марта 2012

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

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' );
        };
    };
};
0 голосов
/ 09 февраля 2015

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

    foreach ($this->getElements() as $element) {
        $decorator = $element->getDecorator('label');
        if (!$decorator) {
            continue;
        }
        $decorator->removeOption('tag');
    }
0 голосов
/ 05 октября 2011

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

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

или

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