Я знаю, что я могу удалить лишний материал из каждого элемента отдельно, так
$button ->removeDecorator('DtDdWrapper') ->removeDecorator('HtmlTag') ->removeDecorator('Label');
Мне было интересно, могу ли я добиться того же для всех моих элементов в форме zend?
И как удалить dl-оболочку формы?
Маркус, вот решение, которое я использую, похоже, работает хорошо, надеюсь, он будет вам подходит.
Во-первых, чтобы визуализировать форму без <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
класса, которую мы увидим позже.
Далее, элементы должны быть рассмотрены. Элементы 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
array в качестве декораторов. Если вы хотите выборочно удалить декораторы, вы должны изучить реализацию этого метода и создать аналогичный для удаления декораторов.
Если вы хотите отключить некоторые декораторы для всех ваших форм, создайте класс 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'); }