Pragmatism in the real world

Simple Zend_Form Example

Following on from the Simple Zend_Layout Example, Zend_Form is now in the trunk, so here’s a super simple, complete example that shows it in action:

Zend_Form screenshot1.png

(clearly the form is unstyled :)

You can construct a Zend_Form directly from a config file or can build it in code. This example builds it in code.

Setting up

This example uses the same basic skeleton as the Zend_Layout code with the addition of a forms directory:

Zend_Form Directory Layout.png

As you can see, I’ve added a forms directory within the application subdirectory with our form file, ContactForm.php, in it.

The contact form

To keep the form contained, I’ve put it in its own class which extends from Zend_Form. The file is application/forms/ContactForm.php and so the class is forms_ContactForm so that Zend_Loader can easily load it:

class forms_ContactForm extends Zend_Form 
{ 
    public function __construct($options = null) 
    { 
        parent::__construct($options);
        $this->setName('contact_us');
        
        $title = new Zend_Form_Element_Select('title');
        $title->setLabel('Title')
              ->setMultiOptions(array('mr'=>'Mr', 'mrs'=>'Mrs'))
              ->setRequired(true)->addValidator('NotEmpty', true);
        
        $firstName = new Zend_Form_Element_Text('firstName');
        $firstName->setLabel('First name')
                  ->setRequired(true)
                  ->addValidator('NotEmpty');

        $lastName = new Zend_Form_Element_Text('lastName');
        $lastName->setLabel('Last name')
                 ->setRequired(true)
                 ->addValidator('NotEmpty');
             
        $email = new Zend_Form_Element_Text('email');
        $email->setLabel('Email address')
              ->addFilter('StringToLower')
              ->setRequired(true)
              ->addValidator('NotEmpty', true)
              ->addValidator('EmailAddress'); 
              
        
        $submit = new Zend_Form_Element_Submit('submit');
        $submit->setLabel('Contact us');
        
        $this->addElements(array($title, $firstName, 
            $lastName, $email, $submit));
        
    } 
}

We set the name of the form first and then create five elements; one select box for the title, three text boxes for first name, surname and email address and then finally a submit button. Note that as we have overridden the constructer, we also call up to the parent’s constructor so that all the Zend_Form initialisation happens.

Creating an element is quite simple. Each element is of the type Zend_Form_Element_Xxx where Xxx is the type, such as Text, Submit, Select, etc. We then configure the element how we want it, such as setting a label and adding filters and validators. Finally we add all the elements to the form using the addElements() function.

Note that if you have multiple validators, you can pass in true as the second parameter ($breakChainOnFailure) to stop processing the remaining validators at that point. This can be because the further validators do not make sense or because you only ever want the user to see one message per field to avoid overwhelming them.

Displaying the form

Having defined out form, we need to get it to the screen. In the controller we need the following:

class IndexController extends Zend_Controller_Action
{
function indexAction()
{
$this->view->pageTitle = "Zend_Form Example";
$this->view->bodyCopy = "


This code assigns some variables to the view, then instantiates the form and assigns that to the view also. The view script is similarly simple:

view/scripts/index/index.phtml:

<?php echo $this->pageTitle ;?>
<?php echo $this->bodyCopy ;?>

<?php echo $this->form ;?>

To render the form, we simply echo it. By default, the form is marked up as a definition list and its HTML looks like this:

<form name="contact_us" id="contact_us" enctype="application/x-www-form-urlencoded" action="" method="post"><dl class="zend_form">
<dt><label for="title" class="required">Title</label></dt>
<dd>
<select name="title" id="title">
<option value="mr" label="Mr">Mr</option>
<option value="mrs" label="Mrs">Mrs</option>
</select></dd>
<dt><label for="firstName" class="required">First name</label></dt>
<dd>
<input type="text" name="firstName" id="firstName" value=""></dd>
<dt><label for="lastName" class="required">Last name</label></dt>
<dd>
<input type="text" name="lastName" id="lastName" value=""></dd>
<dt><label for="email" class="optional">Email address</label></dt>
<dd>
<input type="text" name="email" id="email" value=""></dd>
<dt></dt><dd>
<input type="submit" name="submit" id="submit" value="Contact us"></dd></dl></form>

Notice how the setRequired() has resulted in the "required" CSS class name being applied to those elements.

Decorators

If you do not want to use a definition list, then this can easily be changed using decorators. For instance, adding the following to the bottom of the form's constructor after the addElements() call:

$this->clearDecorators();
$this->addDecorator('FormElements')
->addDecorator('HtmlTag', array('tag' => '<ul>'))
->addDecorator('Form');

$this->setElementDecorators(array(
array('ViewHelper'),
array('Errors'),
array('Description'),
array('Label', array('separator'=>' ')),
array('HtmlTag', array('tag' => 'li', 'class'=>'element-group')),
));

// buttons do not need labels
$submit->setDecorators(array(
array('ViewHelper'),
array('Description'),
array('HtmlTag', array('tag' => 'li', 'class'=>'submit-group')),
));

will result in the form being marked up as an unsigned list with each label and element pair inside each <li>. The marked up form looks like this:

<form name="contact_us" id="contact_us" enctype="application/x-www-form-urlencoded" action="" method="post"><ul>
<li class="element-group"><label for="title" tag="" class="required">Title</label>
<select name="title" id="title">
<option value="mr" label="Mr" selected="selected">Mr</option>
<option value="mrs" label="Mrs">Mrs</option>
</select></li>
<li class="element-group"><label for="firstName" tag="" class="required">First name</label>
<input type="text" name="firstName" id="firstName" value=""></li>
<li class="element-group"><label for="lastName" tag="" class="required">Last name</label>
<input type="text" name="lastName" id="lastName" value=""></li>
<li class="element-group"><label for="email" tag="" class="required">Email address</label>
<input type="text" name="email" id="email" value=""></li>
<li class="submti-group"><input type="submit" name="submit" id="submit" value="Contact us"></li></ul></form>

As you can see, the decorator system makes it easy to render our form in the manner we wish. As a note of warning, pay attention to the order of the decorators as it matters!

Processing

The form is now displayed, so when the user presses the button we need to process it. In this example, this is done in the indexAction() controller function, so that the complete function looks like this with the addition in bold:

class IndexController extends Zend_Controller_Action
{
function indexAction()
{
$this->view->pageTitle = "Zend_Form Example";
$this->view->bodyCopy = "<p>Please fill out this form.</p>";

$form = new forms_ContactForm();

if ($this->_request->isPost()) {
$formData = $this->_request->getPost();
if ($form->isValid($formData)) {
echo 'success';
exit;
} else {
$form->populate($formData);
}
}

$this->view->form = $form;
}
}

Firstly we check the the request is a POST using the request object's isPost() function and then we use validate the submitted data using the form's isValid() function. If this returns true, then we have valid data and can process. If the data is not valid, we populate the form's elements with it and then redisplay so that the user can correct appropriately. The default decorators will display an error message next to each element that failed validation.

Conclusion

So there you have it. A very simple example of how to use Zend_Form.

Here's a zip file of this project: Zend_Form_Example.zip (It includes a snapshot of the trunk of the Zend Framework which is why it's 3MB big.)

It works for me, at least.

Update

With the release of Zend Framework 1.5, a change was made to the way buttons work and you should not put a label decorator on a button as the label property of a button is used for the text value of the button itself.

I have updated the code above to show that if you use setElementDecorators() you then need to reset the decorators for any buttons, the $submit button, in this case. I have also put back the Errors decorator when using an unsigned list.

109 thoughts on “Simple Zend_Form Example

  1. You might want to reformat the code … it all seems to want to fit on one (or very few) lines, which makes it look nasty :/

    Nice article. Presumably there is a way of getting the reasons for validation failing, and displaying them?

  2. DG,

    When validation fails, the default is to display the error message:

    Zend_Form Validation Messages.png

    You can also use $form->getMessages() to collect a nested array.

    Regards,

    Rob…

  3. Nice writeup, Rob. :-)

    One note: the second parameter to a validator, 'breakChainOnFailure', does not act as you specified. By default, *all* validators are run; if *any* of them fails, isValid() returns false (you claimed that if a later one returns true it returns true, which is not the case). However, if you pass true to the breakChainOnFailure argument, you are telling the validation chain that if that particular validator fails, don't run the other validators.

    Why would you do this? Consider: you could have an Alnum validator run first, and a Regex validator run second. There may be no point in running the Regex validator if you already know that the value contains non-alphanumeric characters — so you specify that the Alnum validator should break the chain on failure.

  4. I'm getting:

    Fatal error: Class 'forms_ContactForm' not found in C:xampphtdocssandboxappcontrollersIndexController.php on line 14

    I know I'm doing something wrong, but I can't figure it out. Any help would be appreciated. Thanks!

  5. Matthew,

    You are right (of course!). I've fixed.

    One thing that is weird though is that the NotEmpty validator doesn't appear to work if setRequired is false.
    i.e.

    $email = new Zend_Form_Element_Text('email');
    $email->setLabel('Email address')
    ->addFilter('StringToLower')
    ->setRequired(false)
    ->addValidator('NotEmpty')
    ->addValidator('EmailAddress');

    never produces a message when the field is empty, but will produce one if an invalid email address is entered.

    Regards,

    Rob…

  6. Hi.
    How can i use this example to pre-fill values in the form (for an edit-action)?
    In an earlier Zend_Form proposal i saw something like this:

    $form->setDataSource($this->getParams());

    This fill the form with the submited datas, to display the form again with the same values (when a validation-error occurs)…
    So, how can i do this in 1.5 preview? Other question: it is the same, when i fill the form with values from a database?

  7. Sorry, i didn´t saw this line: "$form->populate($formData);" ;-) So, ok, my first question is answered.

    But the last one: how can i fill out the formvalues from database to display the form at first time?

  8. Rob — by default, when setRequired(false), the 'allowEmpty' flag is enabled. If you don't want to allow that (i.e., force validation if the element is present, even when empty), do setRequire(false)->allowEmpty(false);

  9. Basty — pull the values from your database, cast to an array, and pass to populate:

    $form->populate($results->toArray());

    (assuming you're taking a Zend_Db_Table_Row and passing it to the form)

  10. How can I put 2 elements on one line? Let's say for this example, Title on line 1, first Name and last Name on line 2, and email on line 3.

  11. this – I don't know the zend code to do it but I would put an id on the (li) that surround those 3 fields. Then using CSS I would float:left the first and last name LI's and leave the title and email LI's as display:block(the default)

  12. I dont think there should be any logic for the forms. The article is cool. The idea is cool.

    The folks who are familiar with Apache Struts, imitating the way Struts does validation to Php is much easier and robust. Also adding a bit of Hibernate or ActiveRecord to it, would be nicer.

    No offense, but also the .phtml looks funny there. You can use smarty instead.

    Overall, good article.

  13. Rob,
    Thanks for taking the time to put together this intro to Zend_Form. It's really exciting to see these templating tools mature and this is a really valuable contribution on the Zend side.
    @Firat: Form validation, while initially resembles what's in the domain / repository / ActiveRecord models often times evolves into its own animal. I don't think that having validation propogated from an ORM tool all the way up to a form on a page is healthy, especially as the project or the form evolves. Reading the commits on the Jira tracker, it's clear that Matthew is aware of this and is designing these forms with a pluggable architecture that will enable partial validation (via asynchronous postback) while the user fills out the form.

  14. Thanks.

    Maybe it's the OCD, but I really don't like the way Zend_Form outputs the markup. If you want to clean it up, you have to edit some of the decorators and the view helpers as well. Kind of a pain in the ass, but I like the markup to be formatted nicely (n and t where they should be) if I need to debug it.

  15. @anon: If you don't like the way Zend_Form does markup, the beauty is that you can alter that however you wish: you can drop in replacement decorators and/or view helpers, or you can even use things such as the ViewScript decorator and create view scripts that create your markup. This sort of flexibility was built in as we recognized that no two developers markup forms the same; no matter what we chose for the defaults, some people would not like it. So, if you don't like the markup, use your own.

  16. I want to populate the form but I want to get the error messages in another language.
    Is there any way to do this without using Zend_Locale (perhaps I'm able to define it in the function call, I found no such thing in the API)
    What's the best way?

  17. @Matthias: while not yet documented, you can certainly get messages back in the current locale. Simply use the error codes for validation errors as the keys, and then create translations in one of the formats supported by Zend_Translate. Finally, instantiate a Zend_Translate object, point it to your translations, and add it to your form using $form->setTranslator($translate); At this point you should get translated messages.

    Documentation should be available in the repository in the next couple of days.

  18. Thanks Matthew,
    it works fine!
    A simple example to defin my own error message:

    $english = array("isEmpty" => "The field is empty");
    $translate = new Zend_Translate('array', $english, 'en');
    $this->setTranslator($translate);

    But by the way I don't know all errorcodes. Can I find them anywhere in list form.

  19. Ive been having a tough time trying to set event handlers in a config file.

    How would I set an onchange handler for a Zend_Form_Select element?

    This doesnt work:
    elements.mySelect.onchange = x

    …and neither does this:
    elements.mySelect.options.onchange = x

    …nor this
    elements.mySelect.attribs.onchange = x

    In the programmer docs, an onclick event is assigned to a Zend_Form via the attribs, but I saw no examples of js event handlers being assigned to Zend_Form_Element_X…

    any ideas?

  20. @Steve: first, you should be asking questions on the fw-mvc mailing list. Second, your second form, "elements.mySelect.options.onChange" is the format to use, and when I just tested, worked as expected.

  21. How can I change the default decorator !

    I don't understand why zend_form use "dt" and "dd" ???

    I was largely sufficient to put the label and the field into a div.

    Might be is for SEO or semantic purpose ?

    Seems that with addDecorator you can replace dd, dt but not remove it and place a div arround twice…

    Anyone could explain how can I achieve this.

  22. Sebastien,

    Call $this->clearElementDecorators(); to clear before adding your new ones.

    Regards,

    Rob…

    Update: don't do this!

  23. @Sebastien: There was much debate on the fw-mvc list over the default decorators to use. dl lists are a popular way to markup forms as they are easy to style in such a way that labels and elements appear side-by-side in fixed-width columns.

    @Rob: $this->clearElementDecorators() does not exist. :-) Calling $form->setElementDecorators() will actually overwrite existing decorators on all elements, and calling $element->setDecorators() does as well; no need to call clearDecorators().

  24. *laugh*

    That's what happens when I respond using my mobile whilst at a party with my son…

    Regards,

    Rob…

  25. Hi Rob,
    Thanks for taking the time writing tutorials like this. I really appreciate the work you are doing.
    I only have one question to this example:
    when I use the provided zf distribution from the .zip file I get the following code for the selectbox:

    Mr
    Mrs


    , but when using the zf distribution from the trunk I get:

    Mr
    Mrs

    Why?

    I'm new zf, so I apologize if the reason for this should have been obvious…

    Keep up the good work.

    Jørgen

  26. Ooops,

    the difference wasn't too easy to see…

    It is:

    select name="title" id="title"

    with your distr. and:

    select name="title[]" id="title" multiple="multiple"

    with the trunk.

    cheers,
    Jørgen

  27. Thanx for this turorial. I like the way Zend_Form works. but it seems that I cannot render a Zend_Form easely without the MCV structure. I get the error 'cannot render without a registered view object'. I thought the whole idea behind the zend framework was that components could be used more or less independantly. Why do the default settings require the zend MVC?
    cheers,
    Sjoerd

  28. Sjoerd: Zend_Form uses Zend_View by default, not the whole MVC. The rationale behind this is that Zend_View has a rich set of helpers and functionality already for dealing with the creation of and escaping of HTML form elements; it makes no sense, particularly in light of the DRY principle, for Zend Framework *not* to use them.

    Zend_View is very lightweight, and would not be a huge addition to your project. Since it returns its content, instead of outputting it, you can use it safely from within another view layer should you so choose.

    Additionally, you can override the various decorators to use non-Zend_View-aware alternatives. This approach would allow you to eliminate Zend_View entirely should you so choose.

  29. Textareas generates rows="24" cols="80" by default in the markup, how can I remove just these two attributes? I want to control that through css only, but I can't figure out how to remove them.

  30. Hi Jay,

    Acccording to the spec the rows and cols attributes are required. Just ignore them and style as you want.

    Regards,

    Rob…

  31. Thank you for your answer, I wasn't aware of them being required, good to know. So if I would like to change their values I would do it through decorators? They don't list under getAttribs or getDecorators, but there must be an easy way to change them without clearing all decorators and start over for every textarea.

  32. Jay: all element properties are used as HTML attributes. So you can use $element->rows = " and $element->cols = ", or use $element->setOption('rows', ") to set them. They'll then get propagated to the view.

  33. I was just wondering if it was possible to cache the zend_form object? It would be faster and it would use less resources. No?

  34. Sinus: Zend_Cache has the ability to serialize objects, and can be used to cache your form. You could also consider simply caching the form output (from the landing page, before any values are provided), which would give you a boost for the most commonly viewed version of the form.

  35. Can you please tell us more about the Decorators?
    What are they doing exactly and why they are in that order?

  36. Hi and thanks for this tutorial!!

    I've written some code following this example, but I get the following error when I navigate to the form page:
    Fatal error: Class 'forms_UserAddForm' not found in /xxxx/application/controllers/UserController.php on line 52 where line 52 is "$form = new forms_UserAddForm();"

    I load class Zend_Form in my project index.php file. I've tried loading class forms_UserAddForm too, but it doesn't work (it says "file loaded but class not found").

    I think I'm not loading something that's required, but I'm new to Zend Framework and I'm a bit lost ¬¬

    Any idea??

  37. Oh! I forgot… In index.php (where I set BaseUrl, ControllerDirectory, etc) I've also included:
    set_include_path('.' . PATH_SEPARATOR . './library' . PATH_SEPARATOR . './application/models/' . PATH_SEPARATOR . './application/forms/' . PATH_SEPARATOR . get_include_path());
    But, as I said, it doesn't work…

  38. Dave,

    What did you name the class within forms/UserAddForm.php ?

    Also, the directory that is a parent of forms/ needs to be on your PHP include_path.

    Rob…


  39. if ($this->_request->isPost()) {
    $formData = $this->_request->getPost();
    if ($form->isValid($formData)) {
    echo 'success';
    exit;
    } else {
    $form->populate($formData);
    }
    }

    The html tags might throw someone off :)

  40. Eehh – apparently the page is taking my bold tags into effect, but not yours..

    What I was trying to say is in the "Processing" section you have some naked bold tags.

  41. Jack — there's no reason to populate the form after validation — isValid() populates the form with the data provided. Only call populate if you want to provide defaults for some values.

  42. [quote]
    The form is now displayed, so when the user presses the button we need to process it. In this example, this is done in the indexAction() controller function, so that the complete function looks like this with the addition in bold:

    class IndexController extends Zend_Controller_Action
    {
    function indexAction()
    {
    $this->view->pageTitle = "Zend_Form Example";
    $this->view->bodyCopy = "Please fill out this form.";

    $form = new forms_ContactForm();

    if ($this->_request->isPost()) {
    $formData = $this->_request->getPost();
    if ($form->isValid($formData)) {
    echo 'success';
    exit;
    } else {
    $form->populate($formData);
    }
    }

    $this->view->form = $form;
    }
    }
    [/quote]

    I the bold tags are supposed to make the code bold correct? If not then I'm an idiot and please enlighten me :)

  43. Jack — all looks fine with that example, except, as noted previously, you don't need to call populate() if you've already called isValid(); isValid() populates the form with the data provided to it, so calling populate() if isValid() fails is simply redundant. Just drop the else condition from there, and you'll be fine.

  44. Hi,

    The form doesn't display xhtml valid even if you have doctype('XHTML1_STRICT'); ?> at the top of the layout script, you need call $this->view->doctype('XHTML1_STRICT'); before the form is created. Is there a better way to this?

  45. Vova,

    I'm not quite sure what you mean. If you mean that labels automatically escape html, then that's right. You can turn it off – look for the escape attribute.

    Rob…

  46. Hi there.

    Guys….how about trying to fill any select box with a mySQL returned data ?

    Cannot get it :S

    like: SELECT id,name FROM category
    now, how to set this to my SelectBox ?? Populate doesnt seems to work, or maybe im doing something wrong…

    any ideas?

  47. $select = new Zend_Form_Element_Select('list');
    $select->setLabel('list')
    ->addValidator('Int')
    ->setRequired(true);

    $data = new Table;
    foreach ($data->fetchAll()->toArray() as $listItem) {
    $select->addMultiOption($listItem['id'], $listItem['name']);
    }

    Is that the kind of thing you're looking for?
    Populate will only set the post or current value, so after generating teh select list you would then use populate to select the correct value on postback or when validating and displaying errors.

  48. instead of addDecorator to the submit button, i end up with:

    $submit->removeDecorator('Label');

    pd: thanks for your help.

  49. ok, but with the sample code posted here, im getting labels for submit buttons, so i need to remove the label decorator on that element.

    im using 1.5 so i guess it has to do with the setDecorators part.

    greetings.

  50. Rumeau,

    That's a good idea :)

    Matthew,

    If you use setElementDecorators() then you get a label added onto submit buttons again as it is not clever enough to know never to add a label to an instance of Zend_Form_Element_Button.

    Regards,

    Rob…

  51. Is it just me or does the method getPost() not appear to be available from _request? I'm sure I'm missing something simple!

  52. Durden,

    If you are checking via autocomplete, then it doesn't come up as the docblock comments mark the request member object as a Zend_Controller_Response_Abstract rather than the specific Zend_Controller_Response_Http.

    Zend_Controller_Response_Http is where getPost() is.

    Regards,

    Rob…

  53. Thanks for that Rob…

    The problem I'm having is I have a form on the indexAction of the IndexController. This form has an action to submit to the LoginController::indexAction(). There doesn't appear to be be anything in the post when in the indexAction of the LoginController.

    Any help would be greatly appreciated.

  54. FYI — As of the new stable Zend 1.5, if you used setValue() for any buttons (I would use them to change Add buttons to Update buttons using the same form class), it will no longer work — you must use setLabel() instead.

  55. Hello Rob,

    Thanks for sharing this tutorial. I had the sam error as Chuck, then I added the contact form by adding a 'require_once' line.
    Now I get the error: "Fatal error: Class 'Zend_Form' not found in /var/www/application/forms/ContactForm.php on line 2
    "

    I dont want to manually add everywhere require_once instructions. How can i make sure that is will load automatically?

  56. Hi again Rob. I'm back from holidays and still fighting with the same error.

    My form class in forms/UserAddForm is defined by "class forms_UserAddForm extends Zend_Form" and I've included forms/ parent directory (for me that's application/) with "set_include_path('.' . PATH_SEPARATOR . './library' . PATH_SEPARATOR . './application/models/' . PATH_SEPARATOR . './application/forms/' . PATH_SEPARATOR . './application/' . PATH_SEPARATOR . get_include_path());".

    But it only shows the same error: "Fatal error: Class 'forms_UserAddForm' not found in /application/controllers/UserController.php on line 52"

    I've tried changing the name of the class from forms_UserAddForm to UserAddForm so the file name and the class name are the same, but it doesn't work anyway…

    Thanks for your help!

  57. Dave,

    I suspect that the include path is wrong. Have you downloaded the Zip file and tested that?

    Regards,

    Rob…

  58. Well,

    I have my include path in my bootstrap file and it looks like this:

    define('ROOT_DIR', dirname(dirname(__FILE__)));

    // modify include path to include path to library
    ini_set('include_path', ini_get('include_path'). PATH_SEPARATOR. '../library');
    ini_set('include_path', ini_get('include_path'). PATH_SEPARATOR. '../application');

  59. I have changed it and still get this error:

    "Fatal error: Class 'forms_PersonForm' not found in /var/www/application/controllers/PersoonController.php on line 51"

    you can see it at:
    http://217.149.198.122/persoon/new

    my inlcude path looks like this:

    set_include_path('.'
    . PATH_SEPARATOR . ROOT_DIR.'/application/'
    . PATH_SEPARATOR . ROOT_DIR.'/library/'
    . PATH_SEPARATOR . get_include_path()
    );

  60. Thanks for your help Rob!! Finally I found the problem, a stupid, tiny spell error in the path names…

    Thanks again!!

  61. What if I need a form wrapped into html table with multiple columns and also need to integrate a js pop-up calendar for one of the form fields? In this case "decorators" concept becomes quite tricky. It could be better to echo such a forms per components in the view script, couldn't it?

  62. Kostyantyn,

    That's what I would do. Zend_Form is more than flexible enough to allow you to do that.

    Regards,

    Rob…

  63. The following is a very basic html markup. Could you advice the zend_form approach for it?

    <form action="" method="">
    <table border="0" cellspacing="0" cellpadding="0">
     <tr>
       <td><label for="user_first_name">First Name</label></td>
       <td><input type="text" name="user[first_name]" id="user_first_name" value="" /></td>
       <td><label for="user_email">Email Address</label></td>
       <td><input type="text" name="user[email]" id="user_email" value="" /></td>
     </tr>
     <tr>
       <td><label for="user_last_name">Last Name</label></td>
       <td><input type="text" name="user[last_name]" id="user_last_name" value="" /></td>
       <td><label for="user_birthday">Birthdate</label></td>
       <td>
         <input type="text" name="user[birthday]" id="user_birthday" value="" readonly="1" />
         <img src="" id="user_birthday_trigger" title="Date selector" />
       </td>
       <script type="text/javascript">
         Calendar.setup({
         inputField  : "user_birthday",
         ifFormat    : "%Y-%m-%d",
         button      : "user_birthday_trigger"
         });
       </script>
     </tr>
     <tr>
       <td colspan="4">
         <input type="button" name="save_btn" id="save_btn" value="Save" />
         <input type="button" name="delete_btn" id="delete_btn" value="Delete" />
       </td>
     </tr>
    </table>
    </form>
    
  64. Kostyantyn — you may want to look at the ViewScript decorator, as it gives you the most flexibility. With most of your elements, you could use a combination of standard decorators if you stack them correctly, while using the ViewScript decorator on the form itself so you get things in the appropriate rows.

    I would recommend the array('ViewHelper', 'Errors', array('HtmlTag', array('tag' => 'td')), array('Label', array('tag' => 'td'))) as the decorator stack for most of your elements.

    Honestly, though, if you have questions about decorators, it would be better for you to ask them on the #zftalk IRC channel or fw-mvc mailing list.

  65. Matthew, how to attach Calendar javascript in this case (or autocompletion e.t.c)?

  66. Hi Rob.

    I'm trying to edit data using Zend_Form. As Matthew told Basty (22/02/2008) I pull the values from my database (using Zend_Db_Table_Row), cast them to an array and pass them to populate.
    My problem is that I have a couple of columns in my database which have binary values ('0' or '1') and I want to show them in my form with a checkbox (checked = 1 and unchecked = 0). It works when I'm adding new info to my database, but when I populate the form with existing data (edit action) they always appear checked. So, how can I get them checked only if the database's value is '1'??

    Thanks!!

  67. Hi Dave,

    In your form can't you do something like:

    $tickbox = new Zend_Form_Element_Checkbox('box);

    if ($value_from_database == 1) {
    $tickbox->setCheckedValue('1')
    } else {
    $tickbox->setCheckedValue('0')
    }

    and then set the labels etc up as normal. Or am I misunderstanding?

  68. I am having trouble with the
    Zend_Form_Element_MultiCheckbox() method.

    I keep getting:
    Fatal error: Call to undefined method Zend_Form_Element_Checkbox::addMultiOptions() in /home/adamrifat/ultimateworks/forms/CreateContractorForm.php on line 29

    or

    Fatal error: Class 'Zend_Form_Element_Multi_Checkbox' not found in /home/adamrifat/ultimateworks/forms/CreateContractorForm.php on line 28

    am I doing something wrong?

    I am simply writing

    $services = new Zend_Form_Element_MultiCheckbox('services');

  69. Hi Rob,

    Can you explain decorators? I read the zend manual and am still lost. Your form example shows the fields on one line in IE. How would I change the to a

    I just get get my head around this.

    Thanks
    Frank

  70. Similarly confused as to how to decorate the form and elements. I have found no clear examples as to how to accomplish this.

    There's lots of stuff in the manual about decorators, and I've got some of it to work on your sample, but it's not clear to me how to do things like
    1) wrap the form elements in a div with a specific classname
    2) create a standard look and feel for all forms
    3) override that look and feel for a specific form.

    If you can point me in a direction that would be cool.

  71. Sam, an obvious answer is to wrap the form in a div in the view script. I.e.

    form; ?>

    but this may not work I suppose if you are using the layout engine.

    You can style a form with css. dd and dl lists can easily be styles with css as can input fields, labels etc etc.

    For a specific form you can also use css selectors. E.g.

    and then you can write a style such as div#form1 .form {}

    which only applies to forms with an ID of form1.

    I too haven't properly got my head around decorators either so I might be completely missing the point.

    Still can't get the Form_Element_MultiCheckbox class to work though.

    Anyone got any thoughts on that?

Comments are closed.