Developer Area/Core Subsystems/Form API (Pieforms): Difference between revisions
From Mahara Wiki
< Developer Area | Core Subsystems
(→Rules) |
|||
(4 intermediate revisions by the same user not shown) | |||
Line 37: | Line 37: | ||
There are some inbuilt rules available for every element, such as "required", "minlength" and "maxlength". Both elements in the example form are required. These checks are performed before the validate function is called and will automatically set errors, which is why the check to get_error is made. | There are some inbuilt rules available for every element, such as "required", "minlength" and "maxlength". Both elements in the example form are required. These checks are performed before the validate function is called and will automatically set errors, which is why the check to get_error is made. | ||
====the testform_submit function==== | ====the testform_submit function==== | ||
This function is named after the form name, with <code>_submit</code> on the end. It takes an array of the submitted values that have already been validated successfully according to the validation rules set on the form. From here you can do almost anything, but the last thing that you should do is somehow display another page, otherwise the form will be re-presented to the user. | This function is named after the form name, with <code>_submit</code> on the end. It takes an array of the submitted values that have already been validated successfully according to the validation rules set on the form. From here you can do almost anything, but the last thing that you should do is somehow display another page, otherwise the form will be re-presented to the user. | ||
You can still checks here and return errors via $form->set_error() if there are problems with saving / updating data at the database level. | |||
Most of the time you will display another page by using the [http://mahara.eduforge.org/api/mahara/core/_lib---mahara.php.html#functionredirect <span style="white-space: nowrap">[[Image:http.png]]redirect</span>] function, which takes you to another page. To set a success/fail message, you can use the <code>$SESSION</code> object to add messages, and they will be displayed on the next page that the user visits. | Most of the time you will display another page by using the [http://mahara.eduforge.org/api/mahara/core/_lib---mahara.php.html#functionredirect <span style="white-space: nowrap">[[Image:http.png]]redirect</span>] function, which takes you to another page. To set a success/fail message, you can use the <code>$SESSION</code> object to add messages, and they will be displayed on the next page that the user visits. | ||
====The pieform($form) function call==== | ====The pieform($form) function call==== | ||
This call builds the form | This call builds the form and returns the HTML for the form for display. | ||
* If the form has been submitted then this call builds the form again and validates the submitted values from the browser against the rebuilt form. This way a person can't add / manipulate form fields via the browser DOM. | |||
** If the validation fails the form HTML is returned to the browser with errors showing | |||
** If the validation passes then rebuilt form calls the submit function of the form and does the processing / redirection. | |||
===Form API Terms=== | ===Form API Terms=== | ||
Line 70: | Line 70: | ||
====Rules==== | ====Rules==== | ||
Rules are used to validate elements. Given the element's value, they check if the value matches whatever condition they check | Rules are used to validate elements. Given the element's value, they check if the value matches whatever condition they check. | ||
The inbuilt rules as of 2020/09/18 are | |||
* required - used to indicate if a filed need to be filled in (a form with one or more of this will also put a required message at top of form) | |||
* minlength - used to set what minimum length input has to be | |||
* maxlength - used to set what maximum length input has to be | |||
* email - check if the input is structured like an email address | |||
* before - checking a field order in relation to another field | |||
* integer - make sure the input is a valid integer | |||
* minvalue - making sure integer is above a certain value | |||
* maxvalue - making sure integer is below a certain value | |||
* regex - testing input value against a regex to see if it matches | |||
* oneof - similar to required but for making sure at least one of a set of elements are filled in | |||
* requiredby - similar to required but for making sure that if field X is filled in the field Y is required to be filled in also | |||
* safetext - checks that if the input is cleaned via clean_html that we have a non-empty value left | |||
====Renderers==== | ====Renderers==== |
Latest revision as of 16:38, 18 September 2020
Pieforms is the forms library used by Mahara. It provides a unified way to create, validate and process forms all with a common look and feel, with support for pluggable elements, renderers and validation rules.
Concepts
To create a form, you need three or four things
- A hash containing the form definition. Basically, this is a big array describing overall form properties, and the elements for the form.
- An optional callback function that can be used to validate a form submission.
- A callback function that handles the submission of the form, given that all of the values submitted have been validated
- A call to the form() function, passing the form definition, which manages the entire form building, validating, submitting and displaying process.
A simple form
Here is a simple form definition:
$form = array(
'name' => 'testform',
'method' => 'post',
'action' => '',
'elements' => array(
'login' => array(
'type' => 'fieldset',
'legend' => get_string('login'),
'elements' => array(
'login_username' => array(
'type' => 'text',
'title' => get_string('username'),
'description' => get_string('usernamedesc'),
'help' => get_string('usernamehelp'),
'rules' => array(
'required' => true
)
),
'login_password' => array(
'type' => 'password',
'title' => get_string('password'),
'description' => get_string('passworddesc'),
'help' => get_string('passwordhelp'),
'value' => '',
'rules' => array(
'required' => true
)
)
)
),
'submit' => array(
'type' => 'submit',
'value' => get_string('login')
)
)
);
function testform_validate(Pieform $form, $values) {
if (!$form->get_error('login_username') && !validate_username($values['login_username'])) {
$form->set_error('login_username', get_string('usernamenotvalid'));
}
}
function testform_submit($values) {
global $SESSION;
try {
log_user_in($values);
$SESSION->add_ok_msg(get_string('userloggedinok'));
}
catch (SQLException $e) {
$SESSION->add_err_msg(get_string('couldnotloguserin'));
}
redirect(get_config('wwwroot'));
}
$smarty = smarty();
$smarty->assign('form', pieform($form));
$smarty->display('template.tpl');
Here is a description of each part.
The $form array
This array contains the definition of the form. In this example the form is hard coded, but there's nothing to stop it from being generated dynamically. The array specifies some metadata for the whole form, like its name, method and action target, and then a list of elements that are on the form. Every form must have a name, this name is used to call the callback functions.
More information about the $form array is available on a separate page.
The testform_validate function
This function is named after the form name, with _validate
on the end. It takes an array of the submitted values, and the form that is being validated, and can perform whatever checks are required that cannot be otherwise handled by the inbuilt form rules. If an error is detected, the method $form->set_error
is called, to set an error message on the field.
Using $form->get_element() and $form->get_element_option() methods allows one to compare content in the submitted $values array with the initial default information of the element existing on the $form hash.
There are some inbuilt rules available for every element, such as "required", "minlength" and "maxlength". Both elements in the example form are required. These checks are performed before the validate function is called and will automatically set errors, which is why the check to get_error is made.
the testform_submit function
This function is named after the form name, with _submit
on the end. It takes an array of the submitted values that have already been validated successfully according to the validation rules set on the form. From here you can do almost anything, but the last thing that you should do is somehow display another page, otherwise the form will be re-presented to the user.
You can still checks here and return errors via $form->set_error() if there are problems with saving / updating data at the database level.
Most of the time you will display another page by using the File:Http.pngredirect function, which takes you to another page. To set a success/fail message, you can use the $SESSION
object to add messages, and they will be displayed on the next page that the user visits.
The pieform($form) function call
This call builds the form and returns the HTML for the form for display.
- If the form has been submitted then this call builds the form again and validates the submitted values from the browser against the rebuilt form. This way a person can't add / manipulate form fields via the browser DOM.
- If the validation fails the form HTML is returned to the browser with errors showing
- If the validation passes then rebuilt form calls the submit function of the form and does the processing / redirection.
Form API Terms
Pieforms has several components, a basic description of each is given here.
Elements
Pieform elements are similar to the widgets you have in normal HTML forms, and in fact all HTML widgets have element implementations in Pieforms. However, Pieforms does not limit you to using just the standard HTML widgets - you can write your own elements that have very advanced behaviour, are comprised of multiple widgets, or do almost anything you like.
For example, there is a 'text' element, which represents a simple HTML widget. But there is also a 'date' widget, which is currently rendered as three widgets for year, month, day, a 'wysiwyg' element which represents a full WYSIWYG editor, and a 'userlist' element that is made up of two boxes, with controls to move usernames from one to the other, and even allows ajax searching of the lists!
It's really easy to write your own elements, and they can be reused on any form that needs them. More information about elements, including how to write your own, is available.
Rules
Rules are used to validate elements. Given the element's value, they check if the value matches whatever condition they check.
The inbuilt rules as of 2020/09/18 are
- required - used to indicate if a filed need to be filled in (a form with one or more of this will also put a required message at top of form)
- minlength - used to set what minimum length input has to be
- maxlength - used to set what maximum length input has to be
- email - check if the input is structured like an email address
- before - checking a field order in relation to another field
- integer - make sure the input is a valid integer
- minvalue - making sure integer is above a certain value
- maxvalue - making sure integer is below a certain value
- regex - testing input value against a regex to see if it matches
- oneof - similar to required but for making sure at least one of a set of elements are filled in
- requiredby - similar to required but for making sure that if field X is filled in the field Y is required to be filled in also
- safetext - checks that if the input is cleaned via clean_html that we have a non-empty value left
Renderers
Renders are used to change the containers that elements are rendered inside. For example, there is a 'table' renderer which puts each element inside a table row, and a 'div' renderer that puts them inside a
One thing that the Mahara project has done has added support for contextual help for each element. The renderer will render question marks beside each form element, which when clicked, reveal contextual help for the element. You could add almost any extra information to each element, to assist your form output - for example, a description, help text or raw HTML to be output at a certain point for each element.
Renderers? have their own page for more information (can you tell I'm running out of ways to say the same thing? :)
How they fit together
Here are some statements that might help you describe how a form is put together using the form API.
A form is made up of elements.
Elements are like standard HTML widgets, except they can be more complicated and comprised of many widgets if necessary.
Elements are validated by rules?.
Each element in a form is rendered inside some boilerplate HTML by a renderer?.
When forms are submitted, they are validated using the rules for each element. If validation passes, the form submit callback is called with the values. If validation fails, the form is redisplayed, with the renderer drawing the error messages as returned by the rule for each element next to it.
Other features of the Form API
- As well as customisable elements, renderers and rules, the form API has the following features
- :* send the form by POST or GET
- send the form to different pages for processing (as long as the form definition is available in both the sending and receiving scripts)
- support for cancel buttons - in effect, submit buttons with no validation applied to them
- auto focus of fields in a form on page load, including focussing the first element with an error if there is one
- ajax submission of the form, including display of success/failure notices
- automatic handling of tabindex for each element
- support for just rendering the form and not handling submission if required
- HTML 4.01 compliance
Major TODO items
- Finish off javascript error setting, preferably so that the error HTML is exported by renderers, and that the 'error' class is set on the elements.
- Handle a tabbed interface type form