I've read the manual many times, I've scoured the posts offered by Google on the subject, I have even bought a couple of books that deal with ZF. Now, why am I still confused?
I can, using Zend_Form, make a form that validates and functions fine. What I cannot do it make a form that looks exactly like I want it to look with the error messages that I want it to have. I want custom buttons, I want funky layouts, I want to insert text in the midst of the form, etc.
Does anyone have a simple way of achieving these sorts of things? Something that makes me feel like the framework is saving me time rather than costing? I could forego Zend Form... make my own form, have its action hit a page to validate and process the posted data and I could do it about as fast as I can type but I really want to "get" this and be able to use it as it was apparently intended.
Any advice? Any simple "how to's" for custom buttons, funky layouts and basic (or rather advanced as there are tons of basic tutorials that skip over the harder issues) "getting things done" with zend form?
Unfortunately, the more complex issues are skipped over because without a real specific purpose or goal in mind, it's really hard to write an example or how-to. I spent some time helping out another developer here on SO who wanted to modify the way hidden elements were displayed, but his case was very specific so it was easier to drill down into specifics.
The majority of the more complex tasks really come down to extending the default helper for a specific field type. For example, I had a project where I wanted to apply the class "error" to all fields that did not pass validation after a form had been submitted instead of writing out the validation error text:
It was a fairly complex process because the actual form element is not available to the view helper by default, so the helper cannot check if the element has a validation error. So I went about the following process:
formXXX()
method, and add a check to see if the element had an error. Additionally, I added asetElement()
method that the decorator could call to set an instance of the element so my helper could check for errors.Zend_Form_Decorator_ViewHelper
. In it, I accessed the view and instantiated the helper for the form element type and checked for the existence of thesetElement()
method I created in my view helper, setting it if it existed. By doing this, I could extend some form element types and not others without busting the entire script.addElementPrefixPath('My_Form_Decorator'), 'path/to/decorator')
) which pointed to my new form decorator.addHelperPath('/path/to/helpers', 'My_View_Helper');
You can see why writing complex tutorials really requires real world problems. The great part about setting up these kinds of helpers, or complex decorator schemes is that, all be it annoying up front, it allows you to very easily create many forms that adhere to the same design scheme and modify their output uniformly very quickly if changes need to be made. But if on the other hand you feel like you're spending a great deal of time figuring out how to do what should be a simple task for the benefit of one form, I would say skip it!
If you would like help for something more specific, however, I would be more than happy to help. Just pose another question (or update this one) and I'll do my best to help out.
You probably have solved this by now, but I've been doing some work and needed a similar solution.
within the foreach loop, you can add table markup. If you've named your keys for your table rows appropriately, they should match up with the form keys. You could even use a loop that grabs the appropriate subform by key, or even an element by a key. you could skip the foreach loop if you know the keys, and simply say print $subform['somekey']; assuming you set the main form by saying $form->setIsArray(true); (not sure if that last part is strictly necessary, but for complicated forms, it should be set like that anyway.
I removed the default decorators so I could have complete control of printing within each element. Zend_Form ought to have a built-in method for grabbing individual elements a little more easily.. but I think this works pretty well.
Hope that's helpful to someone!
Matthew Weier O'Phinney has started a series of blog posts about Zend_Form decorators:
whycantitbemorethan25c mentioned them above, but ViewScripts give you extremely fine-grained control for rendering forms. Zend_Form is meant to be fast and so it assumes many defaults like standard decorators and orders the element the way they were added to the form object. With the ViewScript you can skip much of that that and place all of your elements however you would like within normal HTML.
Don't skip over the concept of Decorators entirely though. They style the individual elements even if they are used in a ViewScript later. For example, you can use them for error messages as others have suggested.
If you have very complicated form that has multiple data points with similar actions (think of a list of users with active/inactive buttons and a delete button for each) you should consider Zend_Form_SubForm. The subforms can utilize the ViewScripts just like normal forms and if you cascade a form with a ViewScript with subforms with their own ViewScripts you end up with nicely contained logic and presentation that is much more powerful than just a straight form.
I'm not sure if Zend already has that feature but, a quick solution would be to extend the class , make it accept a html template.
For example:
template:
Sean McSomething's first advice is the way to go for me. I've always thought that doing
<?php echo $this->form ?>
to render a form is too magical. I'll take it a step further though and render individual decorators rather than individual elements via$element->renderDecorator()
magic methods. This way, you won't have to worry about the order in which you defined your decorators. You just need them to be there, and you won't have to add those pesky, unintuitiveHtmlTag
decorators. I made a blog post about this.