Requirements
- Must be de-coupled from Zend_Controller and Zend_View
- Form setup and validation must be possible without Zend_Controller_*
- Should accept data to validate, and not retrieve from environment
- View rendering should be optional
- Must provide separation between validation, filtering, and rendering
- Must be flexible enough to allow non-XHTML rendering schemas
- Must re-use components as much as possible
- Zend_Filter_Input
- Zend_Validate
- Zend_View_Helper_*
- Must be able to do both automated and manual rendering of form items
- Automated rendering
- Must be capable of displaying labels and form elements
- Must re-use existing form helpers
- Must be capable of localization
- Must be AJAX-friendly
- Able to define JS event handlers
- Able to easily display individual error messages
- Automated rendering
- Must be able to order form elements
- Default should be order in which elements are added to form object
- Must be able to load form and individual elements from config objects
- Could be capable of handling multi-page forms
Need to discuss. My first job, every form was a multi-page form, but since then it has been a relatively infrequent task. If we go this route, I like Mitchell Hashimoto's 'form flow' concept – grouping fields into a 'flow item', and then setting the order of flow items: http://framework.zend.com/wiki/display/ZFPROP/Zend_Form+-+Mitchell+Hashimoto. This would require a dependency on Zend_Session, which I'm not particularly excited about (hard to test). Mitchell's 'branches' concept, while interesting and potentially useful, may not fall into the 80/20 rule. It may be good to have a 'Zend_Form_Wizard' or 'Zend_Form_MultiPage' component that would be built on top of Zend_Form at a later date.
Existing Proposals
- Simon Mundy's Zend_Form proposal
- Jurriën Stutterheim's Zend_Form proposal
- Mitchell Hashimoto's Zend_Form proposal
Automatic rendering
- Render form elements with labels
- When errors detected, render with error messages
- AJAX-friendly: use hidden div for error messages
- Use existing or new form helpers for rendering
Manual rendering
- pass in form object
- retrieve form elements
- utilize element to create form item
Validation
- attach validation rules to form elements
- should be independent of action controller
- action helper
- pass in data to validate
- accessors to retrieve:
- validation status
- filtered values
- error messages
- original values
Classes
Zend_Form_Element
- __construct($name, $spec = null)
- $spec would be a Zend_Config object or array; proxies to setConfig()
- (set|get)Name()
- (set|get)Value()
- getRawValue()
- (set|get)Label()
- (set|get)Order()
- (set|get)ViewHelper()
- (set|get)LabelViewHelper()
- (set|get)ErrorViewHelper()
- (set|get)Locale()
- for localization
- addValidator($name, $validator)
- validators would have error messages attached
- getValidator($name)
- getValidators()
- addFilter($name, $filter)
- getFilter($name)
- getFilters()
- validate($value = null)
- isValid($value = null)
- render()
- __toString()
- proxies to render()
- getType()
- returns class name?
- setConfig(Zend_Config $config)
- allow creating item and then loading from config
Zend_Form_Element concrete extensions
- Xhtml (abstract class)
- (set|get)Name($name)
- (set|get)Type($type)
- input type; likely disabled in individual item implementations
- (set|get)Accept($mime)
- (set|get)Align($align)
- (set|get)Alt($alt)
- (set|get)Checked($bool)
- likely only in individual item implementations
- (set|get)Disabled($bool)
- (set|get)MaxLength($len)
- likely only in individual item implementations
- (set|get)ReadOnly($bool)
- (set|get)Size($len)
- likely only in individual item implementations
- (set|get)Src($src)
- likely only in individual item implementations
- (set|get)Id($id)
- (set|get)Title($title)
- (set|get)Class($class)
- (set|get)Style($style)
- (set|get)OptGroupLabel($label)
- likely only for options in select groups
- (set|get)Selected($bool)
- likely only for options in select groups
- (set|get)Cols($len)
- only for textarea
- (set|get)Rows($len)
- only for textarea
- JS events needing accessors:
- tabIndex
- accessKey
- onFocus
- onBlur
- onSelect
- onChange
- onClick
- onDblClick
- onMouseDown
- onMouseUp
- onMouseOver
- onMouseMove
- onMouseOut
- onKeyPress
- onKeyDown
- onKeyUp
- Button (extends Xhtml)
- Checkbox (extends Xhtml)
- File (extends Xhtml)
- May wait on this for a future date
- Hidden (extends Xhtml)
- Image (extends Xhtml)
- Multiselect (extends Xhtml)
- Password (extends Xhtml)
- Radio (extends Xhtml)
- Reset (extends Xhtml)
- Select (extends Xhtml)
- Submit (extends Xhtml)
- Text (extends Xhtml)
- Textarea (extends Xhtml)
Zend_Form_Abstract
Abstract class from which all other form classes inherit. Will provide Xhtml concrete class implementation that has the Xhtml methods as listed below.
Extends ArrayObject in order to allow easy traversal of form elements (foreach style):
- addField($name, $type)
- $type could be a Zend_Form_Element or the name of an element class
- getField($name)
- getFields()
- removeField($name)
- populate(array $values)
- addSection($label, array $fields, $page = null)
- for formatting into sections
- addPage($label, array $fields)
- (set|get)View(Zend_View_Interface $view)
- For rendering, we need a view instance
- validate($field = null)
- allow validating a single field at a time; useful for ajax
- render()
- isValid()
- getValues()
- getRawValues()
- getErrors()
- setDefaults($defaults)
- default values
- render()
- render each element in form
- renderOpenTag()
- renders opening <form> tag; useful when doing custom rendering of form elements
- renderCloseTag()
- renders closing </form> tag; useful when doing custom rendering of form elements
- __toString()
- proxies to render()
Zend_Form_Xhtml (extends Zend_Form_Abstract)
- (set|get)Action($action)
- form action (URL to which to submit)
- should likely allow different accessors for building URLs
- see url view helper
- see url action helper
- (set|get)Method($method)
- form method (get, post)
- (set|get)Enctype($value)
- (set|get)Charset($charset)
- (set|get)Name($name)
- (set|get)Target($target)
- (set|get)Id($id)
- (set|get)Title($title)
- (set|get)Class($class)
- (set|get)Style($style)
- JS events needing accessors:
- onSubmit
- onReset
- onClick
- onDblClick
- onMouseDown
- onMouseUp
- onMouseOver
- onMouseMove
- onMouseOut
- onKeyPress
- onKeyDown
- onKeyUp
Zend_Controller_Action_Helper_Form
Action helper for retrieving a form class
Zend_View_Helper_FormRenderer
Renders a form. Basically, passes view object to form object, and asks the form object to render itself
How other frameworks do forms
Rails
Code generation.
Then creates all controllers and views you need. The views are basically view scripts with view helpers.
Symfony
Code generation.
Basically the same as Rails.
CakePHP
None. Basically, they have the developer do it themselves, only providing validators, filters, and view helpers.
Solar
Solar_Form:
- Build elements from arrays
- populate -> validate -> decision
- View rendering
- each element is associated with a view helper
- form() view helper renders the form object using the individual helpers
ASP.NET
??? The instructions I've been able to find all use a visual IDE, and none show any code showing how to create a form, validate it, and/or
render it.
Django
- Create form class/function
- Creates and utilizes FormWrapper object
- takes a model as an argument
- model has field types
- model pulls data from request to validate and populate model
- returns rendered form
- view script with no helpers – all manual
- takes a model as an argument
CGI::Application::Plugin::ValidateRM
- Provide a form profile
- Indicate what page to display for form, error, and success
- Validates data using Data::FormValidator
- Use hash to define form elements
- filters
- validations
- messages
- Use hash to define form elements
- Optional renders data using HTML::FillInForm
- Uses hash of elements
- type
- value
- name
- attributes
- Uses hash of elements
1 Comment
comments.show.hideSep 26, 2007
Wil Sinclair
Sounds good. Am I right in thinking the proposal is to add the form-field-specific getters/setters to the relevant subclasses of Xhtml? If so, it might be clearer to put them under these classes in the proposal. Also, I'd love to hear more about AJAX!