Krótka piłka – dekoratory w Zend Form

Każdy używający Zend Frameworka wcześniej czy później natknie się na klasę służącą do tworzenia formularzy – Zend Form. Jest to całkiem przydatna klasa i znakomicie się sprawdza. Sprawdza się świetnie do momentu, kiedy nasz webmaster stwierdzi, że jednak ubranie formularza w dl/dt/dd jest już passe i przydało by się np. ubrać go w tagi ul/li. Mnie właśnie dzisiaj przydarzyła się taka sytuacja, a więc ku pamięci wrzucam rozwiązanie:


class Form extends Zend_Form
public function init() {

        $email = new Zend_Form_Element_Text('email');
        $email->setLabel('Email:');
        $email->addValidator(new Zend_Validate_EmailAddress());
        $email->setRequired();

        $firstName = new Zend_Form_Element_Text('first_name');
        $firstName->setLabel('First name:');
        $firstName->setRequired();

        $lastName = new Zend_Form_Element_Text('last_name');
        $lastName->setLabel('Last name');
        $lastName->setRequired();

        $this->addElements(array($email, $firstName, $lastName));
}

 public function loadDefaultDecorators() {
        parent::loadDefaultDecorators();

        $this->_decorators['HtmlTag']['options']['tag'] = 'ul';

        foreach ($this->_elements as $el) {
            if ($el instanceof Zend_Form_Element_Text) {
                $el->removeDecorator('HtmlTag');
                $el->removeDecorator('Label');

                $el->addDecorator('Label', array('tag' => null));
                $el->addDecorator('HtmlTag', array('tag' => 'li'));
            }

            if ($el instanceof Zend_Form_Element_Submit) {
                $el->removeDecorator('Label');
                $el->removeDecorator('DtDdWrapper');
                $el->addDecorator('HtmlTag', array('tag' => 'li'));
            }
        }
    }

}

Co jak i dlaczego ?

Pierwsze na co należy zwrócić uwagę to miejsce modyfikacji dekoratorów – robimy to w metodzie loadDefaultDecorators(). Jest ona wywoływana jako ostatnia metoda w konstruktorze klasy Zend_Form i dzięki temu mamy już dostęp do wszystkich koniecznych obiektów i pól.

Kolejna kwestia na która trzeba zwrócić uwagę to rozróżnienie pomiędzy różnymi rodzajami elementów formularza. Różne klasy mają różne dekoratory w standardzie.

Najbardziej zastanawiający fragment tego kodu to:

                $el->removeDecorator('HtmlTag');
                $el->removeDecorator('Label');

                $el->addDecorator('Label', array('tag' => null));
                $el->addDecorator('HtmlTag', array('tag' => 'li'));

Po co najpierw usuwać a następnie ponownie dodawać te same dekoratory ? Ano po to by zamienić je miejscami ;). Flow dekoratorów jest taki, że każdy dekorator dodany później dostaje cały kontent wygenerowany przez te, które były dodane wcześniej. Dzięki temu możemy hierarchicznie budować strukturę HTML-a.

Btw.
Powyższy kod jest z takiej niezbyt świeżej wersji frameworka. Także, jeżeli coś się zmieniło to z góry przepraszam i chętnie przyjmę kod na nowszej wersji 😉

  1. batman pisze:

    Jakiś czas temu popełniłem klasę Batman_Form. Jeszcze nie trafiła na githuba – czeka na lepsze czasy :) Niemniej można z tej klasy korzystać. Jeszcze nie sprawiła mi problemów.

  2. Tak, widziałem, pewnie się przyda przy okazji :)

  3. Yuriy Kisil pisze:

    Witam,

    ja bym trocha inaczej do sprawy podszedł. W funkcji loadDefaultDecorators() ustawiane są domyślne dekoratory forma, nie jego elementów. Jeżeli chcemy je zmienić to można tą funkcje nadpisać, na przykład tak:
    public function loadDefaultDecorators()
    {
    $this->setDecorators(array(
    ‚FormElements’,
    array(‚HtmlTag’, array(‚tag’ => ‚ul’)),
    ‚Form’,
    ));
    }

    A to co masz w ciele funkcji loadDefaultDecorators(), można zastąpić linijką:
    $this->setElementDecorators(array(‚ViewHelper’, ‚Label’, array(‚HtmlTag’, array(‚tag’ => ‚li’)),’Errors’));

    W twoim przykładzie tego powinno wystarczyć.

  1. There are no trackbacks for this post yet.

Leave a Reply

Informuj mnie o odpowiedziach poprzez e-mail. Możesz również subskrybować wpis bez zostawiania komentarza.