Zapewne każdy, komu przyszło tworzyć formularz z wykorzystaniem komponentu Zend_Form spotkał się z problemem związanym z wyświetlaniem elementów typu hidden – Zend_Form_Element_Hidden.

W celu pozbycia się standardowo generowanych elementów dt i dd, w które są opakowane poszczególne elementy formularza przygotowałem klasę SmartGroup_Model_Form, która dziedziczy po Zend_Form. Natomiast każdy formularz dziedziczy z kolei po SmartGroup_Model_Form, zamiast Zend_Form.

abstract class SmartGroup_Model_Form extends Zend_Form {
  abstract protected function _renderForm();

  public function init() {
    $this->_renderForm();
    $this->_replaceViewDecorators();
  }

  protected function _replaceViewDecorators() {
    $this->clearDecorators();
    $this->addDecorator( 'FormElements' )
         ->addDecorator( 'HtmlTag', array( 'tag' => 'div' ) )
         ->addDecorator( 'Form' );

  $this->setElementDecorators( array(
                   array( 'ViewHelper' ),
                   array( 'Errors' ),
                   array( 'Label' ),
                   array( 'HtmlTag', array( 'tag' => 'div', 'class' => 'form-element' ) )
  ));

  foreach($this->getElements() as $formElement) {
    if( $formElement instanceof Zend_Form_Element_Submit ) {
      $formElement->removeDecorator( 'Label' );
      $formElement->addDecorator( 'HtmlTag', array('tag' => 'div', 'class' => 'form-submit' ) );
    }
  }
}

W metodzie replaceViewDecorators usuwamy więc wszystkie dekoratory, jakie mają zostać zastosowane przez Zend_Form, a więc wspomniane elementy dd i dt. Następnie wskazujemy jakie dekoratory mają zostać wprowadzone, ze wskazaniem, że każdy element ma zostać opakowany w tag div. Dodatkowo w linii 19 wskazujemy, że dla każdego elementu (a raczej pary elementów: label + element) ma być dodana klasa “form-element”.

W ostatnim elemencie tej metody dokonujemy iteracji po wszystkich elementach formularz, aby zastosować indywidualne formatowanie dla przycisku submitującego formularz. Gdy znajdziemy taki element usuwamy przypisany dla niego element label, natomiast dla taga div stosujemy klasę “form-submit” zamiast “form-element”.

Poniżej przedstawiam klasę formularza logowania, dla której w dalszej części wpisu prześledzimy wygenerowany kod html:

class SmartGroup_Form_Login extends SmartGroup_Model_Form {
  protected function _renderForm() {
    $this->setMethod('post');

    $secret = new Zend_Form_Element_Hidden( 'secret' );

    $login = new Zend_Form_Element_Text( 'login' );
    $login->setLabel('Login:')
          ->addFilter('StringTrim')
          ->setRequired(true);

    $passwd = new Zend_Form_Element_Password( 'passwd' );
    $passwd->setLabel('Hasło:')
           ->addFilter('StringTrim')
           ->setRequired(true);

    $submit = new Zend_Form_Element_Submit( 'submit' );
    $submit->setLabel( 'zaloguj' );

    $this->addElements( array( $secret, $login, $passwd, $submit ));
  }
}

W efekcie działania powyższych metod wygenerowany kod html dla formularza wygląda następująco:

<form method="post" action="/login/dologin">
  <div>
    <div class="form-element">
      <input type="hidden" name="secret" value="" id="secret" />
    </div>
    <div class="form-element">
      <label for="login" class="required">Login:</label>
      <input type="text" name="login" id="login" value="" />
    </div>
    <div class="form-element">
      <label for="passwd" class="required">Hasło:</label>
      <input type="password" name="passwd" id="passwd" value="" />
    </div>
    <div class="form-submit">
      <input type="submit" name="submit" id="submit" value="zaloguj" />
    </div>
  </div>
</form>

Niestety okazuje się, że dla elmentu typu hidden został wygenerowany kolejny wiersz opakowany w tag div z klasą form-element. W sytuacji, gdy mamy przygotowane odpowiednie style dla tej klasy, będzie to skutkowało pojawieniem się niechcianej przerwy przed pierwszym elementem formularza. Pół biedy, gdy formularz jest tak prosty, jak powyższy. Gdy jednak będzie on miał więcej pól typu hidden, okaże się że przed widocznymi polami formularza mamy całkiem sporą przerwę.

Istnieje bardzo proste rozwiązanie. Wystarczy bowiem do naszej pętli iterującej po wszystkich elementach formularza dodać kolejny warunek dla elementów typu Zend_Form_Element_Hidden.

if($formElement instanceof Zend_Form_Element_Hidden) {
  $formElement->removeDecorator('Label');
  $formElement->addDecorator('HtmlTag', array('tag' => 'div', 'class' => 'hidden-group'));
}

W efekcie tag div, w którym znajdzie się element typu hidden będzie posiadał klasę “hidden-group”, dla której możemy już ustawić odpowiedni styl, pozwalający nam ukryć nam tą zawartość na stronie, np.

.hidden-group {
  visibility: hidden;
}
Zend_Form i elementy typu hidden
Tagged on:             

One thought on “Zend_Form i elementy typu hidden

Leave a Reply

Your email address will not be published. Required fields are marked *

Social Widgets powered by AB-WebLog.com.