Drupal Form API Short Notes

1). Creating Forms : Constructing a textfield form element:
Code:
------
$form['foo'] = array(
'#type' => 'textfield',
'#title' => t('bar'),
'#default_value' => t('foo'),
'#size' => 60,
'#maxlength' => 64,
'#description' => t('baz'),
);
?>

Note : 'foo' is the name of the form.

2). For submit:
Code:
------
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
?>

3). The element's name property is declared in the $form array, at the very end of the array tree. For example, if an element in the form tree was structured like this:
Code:
-----
$form['account_settings']['username']
?>
...then that element's name property is 'username'--this is the key it will be available under in $form_state['values'], in your validation and submission functions, as the form code flattens the array in this fashion before it passes the key/value pairs. NOTE: if you wish to have the full tree structure passed to $form_state['values'], this is possible.

4). The type of form element is declared as an attribute with the '#type' property.

5). Properties/attributes keys are declared with surrounding quotes, beginning with a # sign. Values are strings.

6). The order of the properties/attributes doesn't matter, and any attributes that you don't need, don't need to be declared. Many properties/attributes also have a default fallback value if not explicitly declared.

7). Don't use the '#value' attribute for any form element that can be changed by the user. Use the '#default_value' attribute instead. Don't put values from $form_state['values'] (or $_POST) here! FormsAPI will deal with that for you; only put the original value of the field here.

8). Example code for Form API:
Code:
------
$period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
$form['access']['timer'] = array(
'#type' => 'select',
'#title' => t('Discard logs older than'),
'#default_value' => variable_get('timer', 259200),
'#options' => $period,
'#description' => t('The timer.'),
);
// Description
$form['details'] = array(
'#type' => 'fieldset',
'#title' => t('Details'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['details']['description'] = array(
'#type' => 'textarea',
'#title' => t('Describe it'),
'#default_value' => variable_get('description', ''),
'#cols' => 60,
'#rows' => 5,
'#description' => t('Log description.'),
);
$form['details']['admin'] = array(
'#type' => 'checkbox',
'#title' => t('Only admin can view'),
'#default_value' => variable_get('admin', 0),
);
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#size' => 30,
'#maxlength' => 64,
'#description' => t('Enter the name for this group of settings'),
);

9). We can create fieldset for grouping the item.

10). Creating the hidden field : $form['hidden'] = array('#type' => 'value', '#value' => 'is_it_here');

11). Notice that the first layer is made up of two form groups, 'access', and 'details', and that inside each of these groups, one layer down, are some individual form elements. Order of construction is important here, as the form building code will default to the constructed order of the $form array when it builds the form. For form groups, the '#type' parameter is set to 'fieldset', and notice how the 'details' form group is made into a collapsed form group with the addition of a few attributes.

12). drupal_get_form does the following :
1). Starts the entire form-building process by getting the $form from the builder function
2). Translates the $form['name'] items into actual form elements
3). Performs any validation and "clean-up" that needs to be done, and calls custom validation functions if declared
4). Submits the form if a submit function is declared, and the form has been submitted
5). Calls any custom theming functions that have been declared
6). Returns an HTML string which contains the actual form.

13). Theming Forms : Including any markup directly as an element in the $form array: There are '#prefix' and '#suffix' attributes, and these will place the declared markup either before or after the form element in question. for example:
Code:
------
$form['access'] = array(
'#type' => 'fieldset',
'#title' => t('Access log settings'),
'#prefix' => '

',
'#suffix' => '

',
);
?>

14). There is a '#markup' type which you can place anywhere in the form, and its value will be output directly in its specified location in the forms hierarchy when the form is rendered. example:
Code:
-----
$form['div_tag'] = array(
'#type' => 'markup',
'#value' => '

',
);
?>

15). Validating Forms : The form API has general form validation which it performs on all submitted forms. If there is additional validation you wish to perform on a submitted form, you can create a validation function. the name of the validation function is the form ID with _validate appended to it. the function has two args: $form and $form_state. $form is the form array of the executed form, and $form_state['values'] contains the form values which you may perform validation on. (Note - in more advanced usage, several forms may share a _validate or _submit function - so if the form's ID is needed, it can be retrieved from $form['form_id']['#value'], or $form_state['values']['form_id'].)

16). hook_validate() : Perform node validation before a node is created or updated.This hook is invoked only on the module that defines the node's content type (use hook_node_validate() to act on all node validations).This hook is invoked from node_validate(), after a user has finished editing the node and is previewing or submitting it. It is invoked at the end of all the standard validation steps, and before hook_node_validate() is invoked.

Code:
------
function hook_validate($node, $form, &$form_state) {
if (isset($node->end) && isset($node->start)) {
if ($node->start > $node->end) {
form_set_error('time', t('An event may not end before it starts.'));
}
}
}

17). hook_node_validate() :
Code:
-------
function hook_node_validate($node, $form, &$form_state) {
if (isset($node->end) && isset($node->start)) {
if ($node->start > $node->end) {
form_set_error('time', t('An event may not end before it starts.'));
}
}
}