Bardzo często w różnych formularzach musiałem stosować taki schemat postępowania:
- przy dodawaniu wszystkie pola formularza są dostępne do uzupełnienia
- przy edycji część pól nie może być zmieniana, ale musi być wyświetlona
Zamiast dodawać atrybut disabled, wolę wyświetlać wartość danego pola jako zwykły tekst.
W przypadku pól tekstowych nie ma najmniejszego problemu – wyświetlałem ich wartość, w przypadku selektorów używałem poniższego zapisu:
<?php $c = $this->form->category_id ?>
<?php echo $c->getMultiOption($c->getValue())?>
Dzisiaj przedstawię przykład tworzenia dekoratora formularza, który skróci powyższy zapis i umożliwi korzystanie z niego w wielu miejscach w aplikacji.
<?php
/**
* Dekorator wyświetla "treść" zaznaczonej opcji elementu
* Jeśli element nie jest selektorem, wyświetlana jest wartość elementu,
* w przypadku pól typu MultiSelect oraz MultiCheckbox,
* zaznaczone elementy są łączone przy pomocy separatora
* @author Marek Pietrzak
*/
class My_Decorator_Selected extends Zend_Form_Decorator_Abstract {
protected $_format = '<span id="%s">%s</span>';
/**
* Wyświetlenie zaznaczonej opcji elementu
* @param string $content
* @return string
*/
public function render($content) {
$element = $this->getElement();
$id = htmlentities($element->getId());
$value = $element->getValue();
if ($element instanceof Zend_Form_Element_Multi) {
// dla obiektów MultiSelect i MultiCheckbox zaznaczone opcje są sklejane
if (is_array($value)) {
$separator = $this->getSeparator();
$options = $element->getMultiOptions();
$selectedValues = array_intersect_key($options, array_flip($value));
$selected = implode($separator, array_map('htmlentities', $selectedValues));
} else {
// w przeciwym razie pobieramy zaznaczoną opcję
$selected = htmlentities($element->getMultiOption($value));
}
} else {
// domyślnie zwracana jest wartość obiektu
$selected = $value;
}
return sprintf($this->_format, $id, $selected);
}
}
Klasę nazwałem My_Decorator_Selected, a więc należy ją umieścić w pliku library/My/Decorator/Selected.php i nie zapomnieć o dodaniu do pliku application.ini:
autoloadernamespaces[] = "My_"
Klasa dziedziczy po Zend_Form_Decorator_Abstract, a więc musi implementować metodę render($content). Zmienna $_format przechowuje format w jakim zostanie wyświetlony wynik działania dekoratora. W metodzie render() pobieram dekorowany element, potem jego id i wartość.
Następnie sprawdzam czy element dziedziczy po Zend_Form_Element_Multi (czyli jest selektorem, checkboxem lub polem typu radio). Jeśli nie – w wynikowym <span> będzie wyświetlona jego wartość. Jeśli tak, sprawdzam czy jego wartość jest tablicą. Gdy nie jest – pobieram wartość zaznaczonej opcji, w przeciwym przypadku pobieram separator i za jego pomocą sklejam wszystkie zaznaczone wartości.
Przykłady wywołania:
<pre>
<?php
$options = array('adin' => 'jeden', 'dwa' => 'dwa', 'tri' => 'trzy');
/* multiselektor */
$ms = new Zend_Form_Element_Multiselect('multiselektor');
$ms->addMultiOptions($options)
->addDecorator(new My_Decorator_Selected(array('separator' => PHP_EOL)))
->setValue(array('adin', 'tri'));
echo $ms->renderViewHelper() . PHP_EOL;
echo $ms->renderSelected();
echo PHP_EOL . '***************************' . PHP_EOL;
/* selektor */
$s = new Zend_Form_Element_Select('selektor');
$s->addMultiOptions($options)
->addDecorator(new My_Decorator_Selected())
->setValue(array('dwa'));
echo $s->renderViewHelper() . PHP_EOL;
echo $s->renderSelected();
echo PHP_EOL . '***************************' . PHP_EOL;
/* multi checkbox */
$c = new Zend_Form_Element_MultiCheckbox('checkbox');
$c->addMultiOptions($options)
->addDecorator(new My_Decorator_Selected(array('separator' => ', ')))
->setValue(array('adin', 'tri'));
echo $c->renderViewHelper() . PHP_EOL;
echo $c->renderSelected();
echo PHP_EOL . '***************************' . PHP_EOL;
/* radio */
$r = new Zend_Form_Element_Radio('radio');
$r->addMultiOptions($options)
->addDecorator(new My_Decorator_Selected())
->setValue(array('adin'));
echo $r->renderViewHelper() . PHP_EOL;
echo $r->renderSelected();
echo PHP_EOL . '***************************' . PHP_EOL;
?>
</pre>
Wynik: