Translations
Info
All page names need to be in English.
en da  de  fr  it  ja  km  nl  ru  zh

Form cObj for TYPO3 4.3

From TYPO3Wiki
Jump to: navigation, search
This page belongs to the Core Team (category Core Team)

warning - Message

This document has not been finished yet

Contents

Introduction

The FORM cObj is around for some time. Although TYPO3 has evolved to a Content Management System on Enterprise level, the FORM cObj stayed behind. Although some improvements were made in previous years, the available syntax lacks functionality. For instance, no server side validation is possible and the HTML markup is not according to the latest accessibility standards, although Tsref claims it can be. While working on a improved Form Wizard, to make Forms in the BE without knowledge of Typoscript, I got stuck with this development. I had a lot of functionality stored in my head for the FORM cObj, but never took the time to write this down. Because Typoscript is the base for most of the Content Objects, this had to be evaluated and documented first for the FORM cObj before continuing the development of the Form Wizard.

Current

The goal of the current FORM cObj is to generate a form in the FE to send a mail with the entered values to a receiver, with a little bit of validation, done client side. There is no way to store these values in the database, without using an extension, or to show the user the values in a preview before sending it to the receiver. It's also possible to make a login- or searchform with the cObj, but is IMHO hardly used, because there are better alternatives. Currently there's also the spambot issue. The cObj does not have a validation mechanism if the sender is actually human. We also need an extension for this. More shortcomings are (Add to this list if necessarry, I only wrote down a few):

  • an object which can be used to make forms for your own extension or use for TCA forms in the BE
  • multiple page forms
  • server side validation and a way to choose between server- and clientside with each validation rule
  • multiple validation rules for one element
  • but also validation rules which spans more than one element
  • not all form elements, attributes and behaviours are covered like optgroups, fieldset nesting
  • hooks (when changing the behaviour of the cObj you need to xclass)
  • adding your own validation (actually there is, but not in a very sophisticated way)
  • handling of the submitted data (send by mail, store in database)
  • making form fields combinations like matrixes
  • making special form fields like date
  • redirecting mails to different addresses depending on submitted data
  • filters for the data like trim
  • changing the html markup for each element
  • Separation of markup and code (XFORMS, PDF Forms)
  • Inserting data from database

Also have a look at the document Form Wizard for TYPO3 4.3

Competitors

HTML_QuickForm2

I had a short look into HTML_QuickForm2, an extension for the PEAR library. This one looks very promissing and has a very clean way of adding elements, rules etc. It's written OO. We can learn and adapt a lot from this library. But HTML_QuickForm is only made for generating forms with validation and some minor handling. It doesn't cover a lot of issues which are written above.

Parts of the FORM cObj

The Form

The base of the cObj will be the form itself. You can add elements to it, make validation rules etc.

Elements

The (X)HTML Forms module doesn't have that much elements, but you can do a lot of stuff with it

  • button
  • fieldset
  • form
  • input
  • label
  • legend
  • optgroup
  • option
  • select
  • textarea

One note for the description of the upcoming elements: I've left out the event handlers for the element attributes. All attributes mentioned are optional, unless stated differently

button

Description:

The <button> tag defines a versatile button element for XHTML forms.

Attributes:
  • accesskey
  • class
  • dir
  • disabled
  • id
  • lang
  • name
  • style
  • tabindex
  • title
  • type
  • value
End Tag:

REQUIRED

Contents:

CDATA. Encloses the HTML element that is the input button, usually an image. The following tags are valid within the <button> tag: a, abbr, acronym, address, applet, b, basefont, bdo, big, blockquote, br, button, center, cite, code, dfn, dir, div, dl, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, hr, i, iframe, img, input, isindex, kbd, label, map, menu, noframes, noscript, object, ol, p, pre, q, s, samp, script, select, small, span, strike, strong, sub, sup, table, textarea, tt, u, ul, var

Valid Context:

The <button> tag is valid within the following tags: a, abbr, acronym, address, applet, b, bdo, big, blockquote, body, caption, center, cite, code, dd, del, dfn, div, dt, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, i, iframe, ins, kbd, label, legend, li, noframes, noscript, object, p, pre, q, s, samp, small, span, strike, strong, sub, sup, td, th, tt, u, var

fieldset

Description:

The <fieldset> element allows authors to group labels and controls that are thematically related.

Attributes:
  • class
  • dir
  • id
  • lang
  • style
End Tag:

REQUIRED

Contents:

HTML forms and the elements to create them. The following tags are valid within the <fieldset> tag: a, abbr, acronym, address, applet, b, basefont, bdo, big, blockquote, br, button, center, cite, code, dfn, dir, div, dl, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, hr, i, iframe, img, input, isindex, kbd, label, legend, map, menu, noframes, noscript, object, ol, p, pre, q, s, samp, script, select, small, span, strike, strong, sub, sup, table, textarea, tt, u, ul, var

Valid Context:

The <fieldset> tag is valid within the following tags: blockquote, body, center, dd, div, fieldset, form, iframe, li, noframes, noscript, object, td, th

form

Description:

The <form></form> tag defines a container for form controls and elements.

Attributes:
  • accept
  • accept-charset
  • action
  • class
  • dir
  • enctype
  • id
  • lang
  • method
  • name
  • style
  • title
End Tag:

REQUIRED

Contents:

Form information, including input fields and submit buttons. The following tags are valid within the <form> tag: a, abbr, acronym, address, applet, b, basefont, bdo, big, blockquote, br, button, center, cite, code, dfn, dir, div, dl, em, fieldset, font, form, h1, h2, h3,h4, h5, h6, hr, i, iframe, img, input, isindex, kbd, label, map, menu, noframes, noscript, object, ol, p, pre, q, s, samp, script, select, small, span, strike, strong, sub, sup, table, textarea, tt, u, ul, var

Valid Context:

The <form> tag is valid within the following tag: blockquote, body, center, dd, div, fieldset, iframe, li, noframes, noscript, object, td, th

input

Description:

The <input /> element is used to input data to Web servers using Web forms.

Attributes:
  • accept
  • accesskey
  • alt
  • align
  • checked
  • class
  • dir
  • disabled
  • id
  • lang
  • maxlength
  • name
  • size
  • src
  • style
  • tabindex
  • title
  • type
  • value
End Tag:

Singleton tag

Contents:

The <input /> tag is a singleton tag and has no contents.

Valid Context:

The <input /> tag is valid within the following tags: a, acronym, address, applet, b, bdo, big, blockquote, body, caption, center, cite, code, dd, del, dfn, div, dt, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, i, iframe, ins, kbd, label, legend, li, noframes, noscript, object, p, pre, q, s, samp, small, span, strike, sub, sup, td, th, tt, u, var

label

Description:

The <label></label> assigns an informative label to form controls (one label to one control).

Attributes:
  • accesskey
  • class
  • dir
  • for
  • id
  • lang
  • style
  • title
End Tag:

REQUIRED

Contents:

Text CDATA. The following tags are valid within the <label> tag: a, abbr, acronym, applet, b, basefont, bdo, big, br, button, cite, code, dfn, em, font, i, iframe, img, input kbd, label, map, object, q, s, samp, script, select, small, span, strike, strong, sub, sup, textarea, tt, u, var

Valid Context:

The <label> tag is valid within the following tags: form

legend

Description:

The <legend></legend> element assigns a caption to fieldsets within forms.

Attributes
  • accesskey
  • class
  • dir
  • id
  • lang
  • style
  • title
End Tag:

REQUIRED

Contents:

Text. The following tags are valid within the <legend> tag: a, abbr, acronym, applet, b, basefont, bdo, big, br, button, cite, code, dfn, em, font, i, iframe, img, input, kbd, label, map, object, q, s, samp, script, select, small, span, strike, strong, sub, sup, textarea, tt, u, var

Valid Context:

The <legend> tag is valid within the following tags:

  • fieldset

optgroup

Description

The <optgroup> element defines groups of options in a select list.

Attributes:
  • class
  • dir
  • disabled
  • id
  • label (REQUIRED)
  • lang
  • style
  • title
End Tag:

REQUIRED

Contents:

HTML. The following tags are valid within the <optgroup> tag: option

Valid Context:

The <optgroup></optgroup> tag is valid within the following tags: select, form

option

Description:

The <option> element defines elements in a select or drop-down list.

Attributes:
  • class
  • dir
  • disabled
  • id
  • label (REQUIRED)
  • lang
  • selected
  • style
  • title
  • value
End Tag:

REQUIRED

Contents:

Text. The following tags are valid within the <option> tag: None

Valid Context:

The <option></option> tag is valid within the following tags: select, optgroup

textarea

Description:

The <textarea></textarea> tag defines multi-line text fields in HTML forms.

Attributes:
  • accesskey
  • class
  • cols (REQUIRED)
  • dir
  • disabled
  • id
  • lang
  • name
  • readonly
  • rows (REQUIRED)
  • style
  • tabindex
  • title
End Tag:

REQUIRED

Contents:

The default text displayed within the box. The following tags are valid within the <textarea> tag: None

Valid Context:

The <textarea> tag is valid within the following tag: a, abbr, acronym, address, applet, b, bdo, big, blockquote, body, caption, center, cite, code, dd, del, dfn, div, dt, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, i, iframe, ins, kbd, label, legend, li, noframes, noscript, object, p, pre, q, s, samp, small, span, strike, strong, sub, sup, td, th, tt, u, var

Markup

For the basics we take the (X)HTML markup, but that doesn't mean the markup can only be (X)HTML. The output must be divided from the code. It must be possible to adapt this to different form rendering techniques like PDF forms, XFORMS or perhaps Flash forms.

(X)HTML

After long investigation, trial and error, we (it was not only me) decided to go for the markup proposed by Cameron Adams on Sitepoint as the basics. This doesn't mean the markup is definite, it can be changed. Related to this is the markup that the Form Wizard is going to use. The Form Wizard is based on the javascript libraries Prototype and Scriptaculous, supported by the TYPO3 core in the typo3/contrib folder. It's drag and drop based and uses the <ol> and <li> as containers for sortables and droppables.

A simple example:

<form action="index.php">  
        <fieldset>  
                <legend>Contact Details</legend>  
                <ol>  
                        <li>  
                                <label for="name">Name:</label>  
                                <input id="name" name="name" class="text" type="text" />  
                        </li>  
                        <li>  
                                <label for="email">Email address:</label>  
                                <input id="email" name="email" class="text" type="text" />  
                        </li>  
                        <li>  
                                <label for="phone">Telephone:</label>  
                                <input id="phone" name="phone" class="text" type="text" />  
                        </li>  
                </ol>  
        </fieldset>
</form>

As you can see it uses ordered lists (<ol>) and list element (<li>) tags combined with the regular tags from the Basic Forms Module and the Forms module from the available (X)HTML Modules provided by W3C.

The reason why we use these elements is that we need some kind of handlers (containers) for different styling. Most of the time a form element contains an input field and its label, which normally will show up next to each other, when no styling has been applied. With the help of some extra tags we can style it in different ways without changing the markup. For each form element in a left-to-right reading system, it's logical to position the corresponding label in one of three ways:

  • directly above the form element
  • in a separate left column, left-aligned
  • in a separate left column, right-aligned

Every method has its own advantages and disadvantages and the use depends on the goal of the form.

Vertical labels have the advantage that it has rapid processing by the user (read from top to bottom) and the label is adjacent to its corresponding input field. A disadvantage is that it increases vertical space.

Left justified labels have the advantage that the labels are easy to scan by the user and it reduces the vertical space. However, the label is not adjacent to the corresponding input field.

Right justified labels have the advantage over left justified labels that the label is adjacent, but the readability reduces.

More information at [[1]] Also have a look at [[2]], an article about label placement and eye movement.

Although form styling is important, it's not the job of the FORM cObj. It just gives you one simple method to style it differently without changing markup.

Accessibility

Two tags in particular are very important for accessibility, which we try to keep in mind all the time. These tags are label and legend. These must be used properly. The legend adds a visual explanation of the grouped related elements by use of a fieldset, the label is the visual explanation for a single form element.

A label should be applied to any form element that doesn't automatically include descriptive text, such as:

  • checkboxes
  • radio buttons
  • textareas
  • text fields
  • select boxes

Submit buttons and submit images don't require label elements, because their descriptions are contained, respectively, in their value and alt attributes.

Of course, you can easily style the text inside the label using CSS, so you can format the label text in your forms in the same way as if you were using a span, p, or div, but using a label has the benefit of being much more accessible than any of those elements.

Required fields and Error messages

Required fields and error messages are often little extra bits of information that you want to convey on a form, and they should be equally as accessible as the text label elements for the form element. In fact, to ensure that they're accessible, they should be included in the label itself.

Required fields

The easiest and most accessible way of indicating the required fields on a form is to write "required" after the form label. This addition is not only read out by screenreaders, but it also means that an extra symbol key doesn't need to be provided for visual users, as is the case should you choose to mark required fields with an asterisk or other symbol. To emphasize the importance of the information, we can add the text "required" inside an em element, which also gives us a stylable element to differentiate the "required" text from the label text:

<label for="name">
	Name: <em>required</em> 
</label>

By embedding the required in em, you can style this differently from the rest of the label. However, the asterisk, or star, has become a common tool for marking required fields. Keep in mind that the asterisk is not accessible. An alternative could be to add the star by use of an image representing a star in the label, with the alt text “required”.

Error messages

Error messages are handled in almost the same way as required markers. In order to be read out as a screenreader user places focus on the appropriate form element, they should form part of the label:

<label for="name">
	Email: <strong>This must be a valid email address</strong> 
</label>

Grouping elements

As you might have seen, we use the fieldset for grouping elements. Hey, this is the purpose of this tag. This is quite easy: wrap all form elements which need to be grouped into a fieldset and give the fieldset a legend. There is also the possibility to nest fieldsets. This makes it in particular easy for radio buttons and checkboxes to group them and give them their own group description by using the legend.

Example:

<fieldset>  
	<legend>Contact Details</legend>  
	<ol>  
		<li>  
			<fieldset>  
				<legend>Occupation:</legend>  
				<ol>  
					<li>  
						<input id="occupation1" name="occupation1" class="checkbox" type="checkbox" value="1" />  
						<label for="occupation1">Doctor</label>  
					</li>  
					<li>  
						<input id="occupation2" name="occupation2" class="checkbox" type="checkbox" value="1" />  
						<label for="occupation2">Lawyer</label>  
					</li>  
					<li>  
						<input id="occupation3" name="occupation3" class="checkbox" type="checkbox" value="1" />  
						<label for="occupation3">Teacher</label>  
					</li>  
					<li>  
						<input id="occupation4" name="occupation4" class="checkbox" type="checkbox" value="1" />  
						<label for="occupation4">Web designer</label>  
					</li>  
				</ol>  
			</fieldset>  
		</li>  
	</ol> 
</fieldset> 

The label for the subgroup actually becomes the legend for the nested fieldset, then each of the checkboxes or radio buttons inside the fieldset receives its own label. The ordered list structure that was put in place at the top level is replicated on this sub-level as well, more for consistency than necessity although it can be very handy if you want to style some of the sub-items.

Using the fieldset has one other big advantage: it makes it possible to have two groups next to each other instead of below each other. It's all about CSS styling.

Validation

In the current FORM cObj it is only possible to validate a single field at the time. But what if you want to validate multiple fields, like comparing the password fields. Another example could be a field becomes mandatory when you fill another field, like a payment: If you select you want to pay with your bank account, you have to fill in the account number, the name of the owner of this account and the city. If you don't want to pay with your bankaccount, these fields are not mandatory.

The way the form can deal with this is to add validation to the form, not the single elements. By using the identifier of the field you can assign the validation to a single field, or using an array of identifiers, multiple fields for one validation rule. We need more default validation rules, especially for handling multiple fields in one validation rule. Also we need the possibility to add your own validation rules very easily, not only by using a regular expression, but also calling a userfunc which handles a particular part of the validation.

Server / client side / Ajax

Currently the validation can only be done client side, which is very wrong. Server side validation is a must, and should always be done after submitting the form.

Two other methods which can be used is client side validation and Ajax, both with some advantages and disadvantages.

There is also the possibility to validate a field when the content of the field has been changed and it loses focus, or when you submit the whole form. This is something that could be solved easily: when a validation rule only uses one element, it can be done on the element immediately, with more fields, it must be done after submitting the form.

Error messages should always be displayed next to the field, but it is wise to display a message at the top of the form as well. Not only the error message can be displayed, but the whole form element can be given a different style, like a red background or a red input field.

My preference is to use server side validation always, and add ajax validation to it, directly on the field. Multiple field validation after submitting the form. But I can imagine people want client side validation as well, to reduce the traffic and processing power of the server.

No decission has been made at this point. Feel free to discuss this.

Typoscript

A simple example how this can be:

TS TypoScript:
lib.form = FORM
lib.form{
	rules {
		1 {
			# First validation rule of the element 'name'
			element = name
			message = Your name is required
			rule = required
		}
		2 {
			# Second validation rule of the element 'name'
			element = name
			message = Your name must contain letters only
			rule = lettersonly
		}
		3 {
			elements {
				1 {
					element = password
				}
				2 {
					element = password2
				}
			}
			message = Passwords don't match
			rule = compare
			show = password2
			method = client
		}
	}
	...

Let's explain what's happening here:

At line 1 lib.form is declared as a FORM cObj.

At line 3 we start to add validation rules

As you can see on lines 4 and 9 we have two validation rules for this form

The first one contains only one element, with the name 'name'. The only validation for this field is that it is required. When nothing has been entered in this field, the message 'Your name is required' will show in the label of this field.

The second rule uses two elements, which are compared to each other using 'equal to (=)'. Other comparisment rules can be used as well. More about that later. This validation will be done client side first. If the two fields are not equal to each other, the message 'Passwords don't match' will show in the label next to the field with the name 'password2'.

Quite simple, isn't it? Although I'm forgetting something here. Both the password fields need to be required too, otherwise when you leave them both empty, the second rule will validate. For each password we need a separate rule as well.

Regular rules

  • required - Value can't be empty
  • maxlength - Value must not exceed n characters
  • minlength - Value must have more than n characters
  • rangelength - Value must have between m and n characters
  • email - Value must be a correctly formatted email address
  • date - Value must be a correctly formatted date
  • datetime - Value must be a correctly formatted date and time
  • time - Value must be a correctly formatted time
  • int - Value must be an integer
  • nonzero - Value must be a number not starting with 0
  • alpha - Characters in the value must be in the range a-z or A-Z
  • num - Characters in the value must be in the range 0-9
  • alphanum - Characters in the value must be in the range a-z, A-Z or 0-9
  • alphanum_x - Characters in the value must be in the range a-z, A-Z or 0-9 but also allows _ and -
  • compare - Compares the values of two fields (more on this below)
  • ereg - The value must match the given regular expression

Only when saving to database:

  • unique - Requires the value to be unique in the whole database
  • uniqueInPid - Requires the value to be unique for the current PID.

The compare rule accepts different operators. These are:

  • eq - Both values must be equal (===) to each other
  • neq - Both values are not equal (!==) to each other
  • gt - Value 1 must be greater than (>) value 2
  • gte - Value 1 must be greater than or equal (>=) to value 2
  • lt - Value 1 must be lower than (<) value 2
  • lte - Value 1 must be lower than or equal (<=) to value 2

File upload rules

  • maxfilesize - The file size must not exceed the given number of bytes
  • mimetype - The file must have one of the mimetypes entered here
  • exttype - The file must have one of the file extensions entered here
  • filename - The filename must match the given regex

Group validation rules

It must be possible to filter on a group of elements as well. For instance, you have two input text fields and only one needs to be filled, but you want to have separate rules for each input field.

Adding your own validation methods

When you need a more complex validation, the FORM cObj should provide a way to send the values to a user-defined method. More or less like the userFunc. The method needs to be registered as a validation rule after which you can use it for the validation of multiple form elements.

More to come about validation rules ... stay tuned

Filtering

Another feature that needs to be in the FORM cObj is a filter for each field. The purpose of this filter is to replace or delete certain input, depending on what is needed. A simple filter would be the trim function. But more importantly could be a RSS attack filter on the input. Filtering should be done before validating and should overwrite the values immediately with the filtered values. There is no feedback to the user. He/she will only notice the changes when the value is displayed in the form, for instance after a field didn't validate.

More to come about filtering ...

Rules

  • trim - Trims whitespaces from the value
  • upper - Converts all characters to uppercase
  • lower - Converts all characters to lowercase
  • double2 - Converts the value to a floating point with 2 decimal positions
  • is_in - Will filter out all characters in the value which are not found in this string
  • ereg - Filter using a regular expression

XSS MUST be covered at all times

Adding your own filtering rules

As already mentioned in the validation rules, it must also be possible to call your own methods/functions for filtering when you want to do more complex filtering of the submitted values.

Actions after submit

In the first phase, and probably only for version 4.3, no multipage forms can be generated. So I will skip this part for now.

  • Confirmation - After submitting the form the user can be presented a confirmation screen, with all the submitted data. The user can check this data and, if he/she made an error, go back to the form to change the data.
  • Email - Mail the submitted data to one or multiple addresses. In the first phase no filter will be available where to send the mail to based on some input of the form. This has been planned for later.
  • Storage - Submitted data will be stored in the database. This is a discussion point if we put it in it right away, or we'll do that after phase 1. IMHO I think this should be done after phase 1.