Ответ 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
);
Не стесняйтесь спрашивать о чем-либо, надеюсь, это поможет вам.