Zend_Form

View: New views
12 Messages — Rating Filter:   Alert me  

Zend_Form

by Simon Corless :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I've just started to actually implement Zend Form, so far it's going well but it seems far too difficult (read over the top) to actually make changes to the way the form is displayed.

Maybe I'm not understanding the documentation properly, but is it possible to remove all the default decorators from the form ($form = new Zend_Form(array('disableLoadDefaultDecorators' => true));) Only seems to remove the default form decorators? I want groups and elements stripped too?

I've done it so far by handling the elements, then the groups, then specific submit button, cancel button and hidden elements, in my opinion I want something clean which I can then put my own code on to without having to disable everything first! (I do realise everyone is different, it just appears the ZF is focusing on trying to do everything, rather than forcing the developer to get their hands dirty!).

Is there a way to change the decorators on all buttons, or all text boxes?

Is it possible, if I develop a concrete layout decorator to render everything, based on the example in the manual (although I can't for the life of me find the example now), to tell the type of each form element and change the rendering?

Sorry if all this has been covered before, I've been scouring the mailing list for examples (and a lot of it has been helpful).

Otherwise it's an excellent addition and I look forward to settling down to it!

Simon

Re: Zend_Form

by weierophinney :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-- SiCo007 <simon@...> wrote
(on Thursday, 27 March 2008, 05:45 AM -0700):

> I've just started to actually implement Zend Form, so far it's going well but
> it seems far too difficult (read over the top) to actually make changes to
> the way the form is displayed.
>
> Maybe I'm not understanding the documentation properly, but is it possible
> to remove all the default decorators from the form ($form = new
> Zend_Form(array('disableLoadDefaultDecorators' => true));) Only seems to
> remove the default form decorators? I want groups and elements stripped too?
>
> I've done it so far by handling the elements, then the groups, then specific
> submit button, cancel button and hidden elements, in my opinion I want
> something clean which I can then put my own code on to without having to
> disable everything first! (I do realise everyone is different, it just
> appears the ZF is focusing on trying to do everything, rather than forcing
> the developer to get their hands dirty!).

The disableLoadDefaultDecorators setting is per object; you need to
specify it for each form, group, sub form, and element separately. (For
the most part, we try not to have the form object communicate global
preferences to the items it contains).

It sounds to me like you might want a setting to of
'disableAllDefaultDecorators' that could be applied to the form and
propagate to all items created with the form; if so, please place a
request in the tracker.

Note, however, that you can specify the decorators you want *during*
configuration, and this will override the defaults (the defaults won't
even be loaded).

> Is there a way to change the decorators on all buttons, or all text boxes?

Yes: it's called extension. :-)

Create your own extensions of these classes and specify the decorators
you want in your subclasses (best way is by overriding the
loadDefaultDecorators() method). Then simply provide a prefixPath for
elements to the form object, and your custom elements will be utilized.
This is the best way to approach a situation where you know you will not
be using the shipped defaults.

Zend Framework classes are built to be extended; that's what OOP is all
about. In a component such as Zend_Form, it's the recommended way of
customizing it to suit your needs. Yes, there are many facilities for
customizing the rendering, but to make the customized rendering
re-usable, the easiest way is to extend the various classes and modify
them for your needs. Each component in Zend_Form has a section on
customization that you can use as a guide.

> Is it possible, if I develop a concrete layout decorator to render
> everything, based on the example in the manual (although I can't for the
> life of me find the example now), to tell the type of each form element and
> change the rendering?

Again, you should probably create your own custom elements, as it's the
cleanest approach.

There are some examples of creating custom elements in the manual, but
if you need more tips, please let me know.

--
Matthew Weier O'Phinney
PHP Developer            | matthew@...
Zend - The PHP Company   | http://www.zend.com/

Re: Zend_Form

by Simon Corless :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks, a further question, what is the preffered way of setting custom validator messages, I couldn't get any of the ways I tried (both setting the message by grabbing the validator, which seems like an extra step, trying to pass the messages in an array in addElement and finally trying to set the message for the alllow empty.

Will there be a simple (preferably as part of addElement) or does it already exist and I just haven't found it?!

Simon

Re: Zend_Form

by weierophinney :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-- SiCo007 <simon@...> wrote
(on Thursday, 27 March 2008, 12:50 PM -0700):
>
> Thanks, a further question, what is the preffered way of setting custom
> validator messages, I couldn't get any of the ways I tried (both setting the
> message by grabbing the validator, which seems like an extra step, trying to
> pass the messages in an array in addElement and finally trying to set the
> message for the alllow empty.
>
> Will there be a simple (preferably as part of addElement) or does it already
> exist and I just haven't found it?!

It's documented and straightforward: You pass an array of error
code/message pairs to the 'messages' key in the params for the
validator:

    $element = new Zend_Form_Element(array(
        'validators' => array(
            array('NotEmpty', false, array(
                'messages' => array('isEmpty' => 'This is a custom message')
            )),
        )
    );

The trick is remembering that 'messages' should be an *array*, and that
it should contain key/value pairs of validation class constants/mesages.

You can also simply use translation files, which are the easier method.
In that case, you provide translations for each validation error code
you want a custom message for, and attach the translator:

    $form->setTranslator($translate);

You can use a translation object even if you only have one language; the
nice part is it future-proofs your site for additional languages. :-)

--
Matthew Weier O'Phinney
PHP Developer            | matthew@...
Zend - The PHP Company   | http://www.zend.com/

Re: Zend_Form

by Simon Corless :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ok so how would i set custom error messages making use of:

$form->addElement('text', 'name', array('required' => true, 'filters' => array('StringTrim', 'StringToLower'), 'label' => 'Name', 'description' => 'A unique name for the action, letters only.'));

As whatever I do I cannot get it to work, from reading the mailing list I assume that it cannot be done in this way?

Therefore I would need to create each element then add each element to the form?

I'm just creating my own selection of elements and hopefully more of it will become clear, you're right it would be easier to use the translation components, however is this not extra burden for my site, when ultimatley it's just in English? (Short sighted maybe, but from an efficiency point of view how does using translation stand as opposed to not using it?).

I'm sure it will come together, it's the transition from using code I've written and know inside out, to using someone elses code and hooking bits on here and there.

Simon

Matthew Weier O'Phinney-3 wrote:
It's documented and straightforward: You pass an array of error
code/message pairs to the 'messages' key in the params for the
validator:

    $element = new Zend_Form_Element(array(
        'validators' => array(
            array('NotEmpty', false, array(
                'messages' => array('isEmpty' => 'This is a custom message')
            )),
        )
    );

The trick is remembering that 'messages' should be an *array*, and that
it should contain key/value pairs of validation class constants/mesages.

You can also simply use translation files, which are the easier method.
In that case, you provide translations for each validation error code
you want a custom message for, and attach the translator:

    $form->setTranslator($translate);

You can use a translation object even if you only have one language; the
nice part is it future-proofs your site for additional languages. :-)

Re: Zend_Form

by weierophinney :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-- SiCo007 <simon@...> wrote
(on Friday, 28 March 2008, 04:37 AM -0700):
>
> Ok so how would i set custom error messages making use of:
>
> $form->addElement('text', 'name', array('required' => true, 'filters' =>
> array('StringTrim', 'StringToLower'), 'label' => 'Name', 'description' => 'A
> unique name for the action, letters only.'));
>
> As whatever I do I cannot get it to work, from reading the mailing list I
> assume that it cannot be done in this way?

Well, no, it can't -- because you don't have any validators associated
with it. You *have* made it required, but because you don't explicitly
set a NotEmpty validator, there's no way to set the message.

Add a validator, and add messages, as I showed you in my previous
message; if you are only testing for NotEmpty, and want a custom
message, add the validator explicitly. Add your validators just like
you've added filters in your example:



> Therefore I would need to create each element then add each element to the
> form?

You need to create elements somehow.

    $form->addElement('text', 'name', array(
        'required' => true,
        'filters' => array('StringTrim', 'StringToLower'),
        'label' => 'Name',
        'description' => 'A unique name for the action, letters only.',
        'validators' => array(
            array('NotEmpty', true, array('messages' => array('custom error message'))),
        ),
    ));

> I'm just creating my own selection of elements and hopefully more of it will
> become clear, you're right it would be easier to use the translation
> components, however is this not extra burden for my site, when ultimatley
> it's just in English? (Short sighted maybe, but from an efficiency point of
> view how does using translation stand as opposed to not using it?).

I can't speak to the performance of the I18N components as I've done no
benchmarking with them, but they wouldn't likely add that much overhead
to your application.

> I'm sure it will come together, it's the transition from using code I've
> written and know inside out, to using someone elses code and hooking bits on
> here and there.
>
> Simon
>
>
> Matthew Weier O'Phinney-3 wrote:
> >
> > It's documented and straightforward: You pass an array of error
> > code/message pairs to the 'messages' key in the params for the
> > validator:
> >
> >     $element = new Zend_Form_Element(array(
> >         'validators' => array(
> >             array('NotEmpty', false, array(
> >                 'messages' => array('isEmpty' => 'This is a custom
> > message')
> >             )),
> >         )
> >     );
> >
> > The trick is remembering that 'messages' should be an *array*, and that
> > it should contain key/value pairs of validation class constants/mesages.
> >
> > You can also simply use translation files, which are the easier method.
> > In that case, you provide translations for each validation error code
> > you want a custom message for, and attach the translator:
> >
> >     $form->setTranslator($translate);
> >
> > You can use a translation object even if you only have one language; the
> > nice part is it future-proofs your site for additional languages. :-)
> >
> >
>
>
> -----
> Simon Corless
>
> http://www.ajb007.co.uk/
> --
> View this message in context: http://www.nabble.com/Zend_Form-tp16324818p16349332.html
> Sent from the Zend Framework mailing list archive at Nabble.com.
>

--
Matthew Weier O'Phinney
PHP Developer            | matthew@...
Zend - The PHP Company   | http://www.zend.com/

Re: Zend_Form

by Simon Corless :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'm trying to disable and reset the decorators on my form but the following does nothing!

If I remove disableLoadDefaultDecorators' => true and the line $form->setDecorators(array('FormElements', array('HtmlTag', array('tag' => 'div')), 'Form')); then the form displays as normal (i.e. dd tags). If I add disableLoadDefaultDecorators' => true, then as expected, nothing shows at all. Therefore I added in the form decorators at the bottom and it displays the form as normal again.

$form = new Zend_Form(array('disableLoadDefaultDecorators' => true, 'elementDecorators' => array(
                'ViewHelper',
                array('Description', array('tag' => 'div', 'class' => 'help')),
                'Errors',
                array('Label'),
                array('HtmlTag', array('tag' => 'div', 'class' => 'field'))
               
            )));
            $form->setDecorators(array('FormElements', array('HtmlTag', array('tag' => 'div')), 'Form'));

Is this remotely the right way to replace the default decorators or am I better off extending the form class outeright?

How do I pass the decorators I wish to use for the form to the constructor? I couldn't see this in the setOptions method.

Your help would be greatly appreciated as I can't believe it is as hard as I am finding it!

Simon

Re: Zend_Form

by weierophinney :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-- SiCo007 <simon@...> wrote
(on Friday, 28 March 2008, 06:03 AM -0700):

> I'm trying to disable and reset the decorators on my form but the following
> does nothing!
>
> If I remove disableLoadDefaultDecorators' => true and the line
> $form->setDecorators(array('FormElements', array('HtmlTag', array('tag' =>
> 'div')), 'Form')); then the form displays as normal (i.e. dd tags). If I add
> disableLoadDefaultDecorators' => true, then as expected, nothing shows at
> all. Therefore I added in the form decorators at the bottom and it displays
> the form as normal again.
>
> $form = new Zend_Form(array('disableLoadDefaultDecorators' => true,
> 'elementDecorators' => array(
>        'ViewHelper',
>        array('Description', array('tag' => 'div', 'class' => 'help')),
>        'Errors',
>        array('Label'),
>        array('HtmlTag', array('tag' => 'div', 'class' => 'field'))
>        
>    )));
>    $form->setDecorators(array('FormElements', array('HtmlTag', array('tag'
> => 'div')), 'Form'));
>
> Is this remotely the right way to replace the default decorators or am I
> better off extending the form class outeright?
>
> How do I pass the decorators I wish to use for the form to the constructor?
> I couldn't see this in the setOptions method.
>
> Your help would be greatly appreciated as I can't believe it is as hard as I
> am finding it!

To set decorators, you pass a 'decorators' array in the options passed
to the constructor. I'm going to reformat your example above and add the
decorators:

    $form = new Zend_Form(array(
        'elementDecorators' => array(
         'ViewHelper',
         array('Description', array('tag' => 'div', 'class' => 'help')),
         'Errors',
         array('Label'),
         array('HtmlTag', array('tag' => 'div', 'class' => 'field'))
        ),
        'decorators' => array(
            'FormElements',
            array('HtmlTag', array('tag' => 'div')),
            'Form',
        ),
    ));

That's all there is to it. There's no reason to add the
'disableLoadDefaultDecorators' option, as if any decorators are provided
during initializaiton, the default decorators will not be loaded.

--
Matthew Weier O'Phinney
PHP Developer            | matthew@...
Zend - The PHP Company   | http://www.zend.com/

Re: Zend_Form

by Simon Corless :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Matthew Weier O'Phinney-3 wrote:
 
    $form = new Zend_Form(array(
        'elementDecorators' => array(
         'ViewHelper',
         array('Description', array('tag' => 'div', 'class' => 'help')),
         'Errors',
         array('Label'),
         array('HtmlTag', array('tag' => 'div', 'class' => 'field'))
        ),
        'decorators' => array(
            'FormElements',
            array('HtmlTag', array('tag' => 'div')),
            'Form',
        ),
    ));
Hmm ok I have copied that directly into my form and nothing, it's still rendering the default code with definition lists. I am stumped, unless I have done something obviously daft (ZF 1.5.1).

The HTMl output is:
<form enctype="application/x-www-form-urlencoded" action="" method="post"><div>
<dt></dt>
<dd>
<input type="hidden" name="id" value="0" id="id" /></dd>
<dt><label for="name" class="required">Name</label></dt>
<dd>
<input type="text" name="name" id="name" value=""></dd></div></form>

And the PHP is as follows:

$form = new Zend_Form(array(
        'elementDecorators' => array(
         'ViewHelper',
         array('Description', array('tag' => 'div', 'class' => 'help')),
         'Errors',
         array('Label'),
         array('HtmlTag', array('tag' => 'div', 'class' => 'field'))
        ),
        'decorators' => array(
            'FormElements',
            array('HtmlTag', array('tag' => 'div')),
            'Form',
        ),
    ));
               
$form->addElement('hidden', 'id', array('validators' => array('Int'), 'filters' => array('Int')));
       
$form->addElement('text', 'name', array('required' => true, 'filters' => array('StringTrim', 'StringToLower'), 'label' => 'Name', 'description' => 'A unique name for the action, letters only.'));

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

Now am I missing something, or doing something insanely stupid? The form creation is copied from your post earlier and the fields etc should be based on the docs.

Well, no, it can't -- because you don't have any validators associated
with it. You *have* made it required, but because you don't explicitly
set a NotEmpty validator, there's no way to set the message.
That was an over sight in my code pasting sorry, i wasn't aware you had to specifically apply the notEmpty validator in order to set it's message, that makes sense though.

You're probably sick of me by now but I would really like to get this working as I can't believe it's really this difficult! Thanks for all your help so far.

Simon

Re: Zend_Form

by weierophinney :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-- SiCo007 <simon@...> wrote
(on Friday, 28 March 2008, 10:38 AM -0700):

>
>
> Matthew Weier O'Phinney-3 wrote:
> >  
> >     $form = new Zend_Form(array(
> >         'elementDecorators' => array(
> >          'ViewHelper',
> >          array('Description', array('tag' => 'div', 'class' => 'help')),
> >          'Errors',
> >          array('Label'),
> >          array('HtmlTag', array('tag' => 'div', 'class' => 'field'))
> >         ),
> >         'decorators' => array(
> >             'FormElements',
> >             array('HtmlTag', array('tag' => 'div')),
> >             'Form',
> >         ),
> >     ));
>
> Hmm ok I have copied that directly into my form and nothing, it's still
> rendering the default code with definition lists. I am stumped, unless I
> have done something obviously daft (ZF 1.5.1).

Okay, I missed something in the previous emails. setElementDecorators()
applies to elements set *before* it is called. When the
'elementDecorators' config option is passed, it is run on all elements
created during configuration -- which you would have to do my passing an
'elements' option to the configuration, with all element configurations.
It can be done, but it's harder to read and debug.

In the example you have, you create the form, and *then* create your
individual elements. However, setElementDecorators(), as mentioned,
applies to *existing registered* elements, not ones added after it is
called.

I'd recommend calling setElementDecorators() on your form object *after*
creating all of your elements and registering them with the form object.

The other option is to create your own subclasses of the elements you
use and override their loadDefaultDecorators() methods to set your own
decorators. This would be the most extensible way to do so.


> The HTMl output is:
> <form enctype="application/x-www-form-urlencoded" action=""
> method="post"><div>
> <dt></dt>
> <dd>
> <input type="hidden" name="id" value="0" id="id" /></dd>
> <dt><label for="name" class="required">Name</label></dt>
> <dd>
> <input type="text" name="name" id="name" value=""></dd></div></form>
>
> And the PHP is as follows:
>
> $form = new Zend_Form(array(
>         'elementDecorators' => array(
>          'ViewHelper',
>          array('Description', array('tag' => 'div', 'class' => 'help')),
>          'Errors',
>          array('Label'),
>          array('HtmlTag', array('tag' => 'div', 'class' => 'field'))
>         ),
>         'decorators' => array(
>             'FormElements',
>             array('HtmlTag', array('tag' => 'div')),
>             'Form',
>         ),
>     ));
>
> $form->addElement('hidden', 'id', array('validators' => array('Int'),
> 'filters' => array('Int')));
>        
> $form->addElement('text', 'name', array('required' => true, 'filters' =>
> array('StringTrim', 'StringToLower'), 'label' => 'Name', 'description' => 'A
> unique name for the action, letters only.'));
>
> $this->view->form = $form;
>
> Now am I missing something, or doing something insanely stupid? The form
> creation is copied from your post earlier and the fields etc should be based
> on the docs.
>
>
>
> > Well, no, it can't -- because you don't have any validators associated
> > with it. You *have* made it required, but because you don't explicitly
> > set a NotEmpty validator, there's no way to set the message.
> >
>
> That was an over sight in my code pasting sorry, i wasn't aware you had to
> specifically apply the notEmpty validator in order to set it's message, that
> makes sense though.
>
> You're probably sick of me by now but I would really like to get this
> working as I can't believe it's really this difficult! Thanks for all your
> help so far.

--
Matthew Weier O'Phinney
PHP Developer            | matthew@...
Zend - The PHP Company   | http://www.zend.com/

Re: Zend_Form

by Steve Clay :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

SiCo007 wrote:
> You're probably sick of me by now but I would really like to get this
> working as I can't believe it's really this difficult! Thanks for all your

No, keep them coming. Zend_Form is really powerful, but nothing this
flexible is going to be trivial to finely configure. Thorough docs and
friendly APIs are essential and every question helps Matt & co. know
where those docs are lacking, or where the API could be simplified.

Zend_Form is a waste of time if only top programmers can get their head
around it enough to modify its output, because every single Zend_Form
user will likely need to do that!

What would be really helpful would be some examples of inputs with
altered markup and the necessary code to achieve them.

--
Steve Clay
http://mrclay.org/

Re: Zend_Form

by Simon Corless :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Matthew Weier O'Phinney-3 wrote:
Okay, I missed something in the previous emails. setElementDecorators()
applies to elements set *before* it is called. When the
'elementDecorators' config option is passed, it is run on all elements
created during configuration -- which you would have to do my passing an
'elements' option to the configuration, with all element configurations.
It can be done, but it's harder to read and debug.
Ok now we're getting somewhere, all be it back where I started a few days ago!

Now I have my form, I have the decoarators specified below the fields (which I wasn't aware of as a requirement), can I ask why it is this way round? I would of thought, surely, it makes sense to specifiy certain things at any stage in the form. Thus default decorators could be specified in the constructor and applied to each element. I just don't see the advantage in doing it afterwards as you tend to overwrite any custom element validators when you reset the whole form anyway... Yes you can remove or add specific decorators, but as this is primarily done on a per element basis, why require the defaults specified after you create the form?

For example, how do I now make my form hide the hidden elements. I have created a custom element with only the viewrender decorator, which works as long as I don't set any other decorators anywhere! Now, however, the decorator gets over written as I reformat the form with my custom decorators for all elements (without using clearDecorators()).

Is the simple answer to place this field after I set the decorators? And the more complex answer (as you mention in your last email) to sub class all the elements and set the decorators? Which in my opinion is unneccessary and a huge duplication of code. Then the non friendly answer would be to manually remove decorators from each hidden field in the form ($form->id->.....).

From my point of view if I create a site based on ZF I need my own framework running on top of ZF to give me the common functionality I want in projects (caching, ACL etc etc). I want my forms to be the same, essentially they run on ZF but I set a common use class to set them up. I see the point of sub classing the elements to make a default long or short text box for example, but I believe the styles should be set centrally. Either in my framework, or left up to me in the particular action. Elements should be dumb to their style (except the hidden fields, which as their nature states should be hidden and out of the flow of my form (not taking into account sub forms)). If I want one field to be bright green, I can simply set the decorator in that specific form after or as I create the field (as you do currently), but this should not be overwritten by an attempt to reset the html used to display a form.

So my question is, how do I make a 'standard' form without creating a new set of elements every time I want a slightly different form? (I admit there is unlikely to be anything that can't be done in CSS, but the point of all this is future proofing and extensibility). I suppose I could sub class Zend_Form for every form I make, but again, that seems like more classes than are required. Even if I did this, it appears I'd have to specify specific decorators for specific form fields I wanted to be different.

In short my goals for a form are: Hidden fields with only the field html in the form, multiple buttons on one line, multiple fields on one line and standard fields displayed along with the description.

I have yet to attempt the multiple buttons and multiple fields on one line , although I have seen it mentioned on the mailing list so that just needs looking at. The other two I'm attempting and failing at!

I look forward to your thoughts, please don't get me wrong I think Zend_Form is an excellent component, I just need to clarify it's workings, as currently it has taken longer to use than a custom implementation using Zend_Filter_Input for example (I realise they are very different!), which I found easy to utilise as I wanted.

I am sure what I want to do is not out of the ordinary and others must have attempted similiar forms...

Simon