Thứ Sáu, 30 tháng 5, 2014

Form API Properties [The Form API]

When  building a form definition in your form building function, array keys are used to specify information about the 
form. The most common keys are listed  in the following sections. Some keys are added automatically by the form
builder.

Properties for the Root of the Form

The properties in the following sections are specific to the form root.  In other words, you can set $form ['#programmed'] = TRUEbut setting $form['myfieldset']['mytextfield'][#programmed'] = TRUE
will not make sense to the form builder.

#action

The path to which the form will be submitted.

#built

Used to ascertain whether a form element has been built yet.

#method

The HTTP method with which the form will be submitted.

Properties Added to All Elements

When  the form builder goes through the form definition, it ensures that each  element has some default values  set. The default
values  are set in _element_info() in includes/form.inc but can be overridden by an element’s definition in hook_elements().

#description

This string property is added to all elements and  defaults to NULL. It’s rendered by the element’s theme function. For example, a
text field’s description is rendered underneath the text field, as shown in Figure 11-2.

#attributes

Additional HTML attributes, such as “class” can be set using this mechanism. The following example sets the CSS class of the
form to search-form”.

<?php
$form[‘#attributes’] = array(‘class’ => ‘search-form’);
?>

#required

This Boolean property is added to all elements and  defaults to FALSE. Setting this to TRUE will cause Drupal’s built-in form
validation to throw an error if the form is submitted but the field has not been completed. Also, if set to TRUE, a CSS class is
setfor this element (see theme_form_element() in includes/form.inc).

#tree

This Boolean property is added to all elements and  defaults to FALSE. If set to TRUE, the $form_state['values'] array  resulting
from a form submission will not be flattened. This affects how you access submitted values  (see the “Fieldsets” section of this
chapter).

Properties Allowed in All Elements

The properties explained in the sections that follow are allowed in all elements.

#type

This string declares the type of an element. For example, #type  = 'textfield'. The root of the form must contain the declaration 
#type  = 'form'.

#access

This Boolean property determines whether the element is shown to the user.  If the element has children, the children will not be shown if the parent’s #access property is FALSE. For example, if the element is a fieldset, none of the fields included in the field set
will be shown if #access is FALSE.

The #access property can be set to TRUE or FALSE directly, or the value can be set to a function that returns TRUE or FALSE when executed. Execution will happen when the form definition is retrieved. Here’s an example from Drupal’s default nodeform:

$form['revision_information'
['revision'] = array( '#access' => user_access('administer nodes'),
#type' => 'checkbox','#title' =>
t('Create new revision'), '#default_value' => $node->revision,);

#after_build

An array of function names that will be calle after the form or element is built.

#array_parents

The array of names of the element's parents (including itself) in the form. This will always match the structure of $form. It is
different from #parents in that #parents lists only the structure used in $form_state['values'], which is flat unless #tree is set
to TRUE.
#attached

A keyed array of type => value pairs, where the type (most often “css”, “js”, and  “library”) determines the loading
technique, and  the value provides the options presented to the loader function.

#default_value

The type for this property is mixed. For input elements, this is the value to use in the field if the form has not yet been
submitted. Do not confuse this with the #value element, which defines an internal form value that is never given to the user  but isdefined in the form and  appears in $form_state['values'].

#disabled

Disables (grays out) a form input element. Note that disabling a form field doesn't necessarily prevent someone from
submitting a value through DOM manipulation. It just tells the browser not to accept input.

#element_validate

A list of custom validation functions that need to be passed.

#parents

This array property is added to all elements and  defaults to an empty array.  It is used internally by the form builder to identify parent elements of the form tree. For more information, see http://drupal.org/node/48643.

#post_render

Function(s) to call after  rendering in drupal_render() has occurred. The named function is called  with two arguments, the
rendered element and  its children. It returns the (potentially) altered element content.

#prefix

The string defined in this property will be added to the output when the element is rendered, just before the rendered element

#pre_render

Function(s) to call before rendering in drupal_render() has occurred. The function(s) provided in #pre_render receive the
element as an argument and  must return the altered element.

#process

This property is an associative array. Each array entry consists of a function name as a key and  any arguments that need to be passed as the values These  functions are called  when an element is being built and  allow additional manipulation of the
element atform building time. For example, imodules/system/system.module where the checkboxes type is defined, the
function form_process_checkboxes() in includes/form.inc is set to be called  during form building:

$type['checkboxes'] = array( '#input' => TRUE, '#process' => array('form_process_checkboxes'),);

#states

Adds JavaScript to the element to allow it to have different active  states.

#suffix

The string defined in this property will be added to the output when the element is rendered, just after the rendered element.


#theme


This optional property defines a string that will be used when Drupal looks for a theme function for this element. For
example, setting #theme = 'foo' will cause Drupal to check the theme registry for an entrthat corresponds with foo.
See the “Finding a ThemeFunction for the Form”  section earlier in this chapter.


#theme_wrappers


Theme function to call for the element, after the element and  children are rendered, but before the
#post_render  functions are called.


#title


This string is the title of the element.


#tree


Used to allow collections of form elements. Normally applied to the "parent" element, as the #tree
property cascades to sub-elements.


#weight


This property can be an integer or a decimal number. When  form elements are rendered, they are sorted by their weight. Those  with smaller weights “float up and  appear higher; those with larger  weights “sink down” and  appear lower on the rendered page.


Form  Elements


In this section, we’ll present examples of the built-in Drupal form elements.

Text Field

An example of a text field element follows:

$form['pet_name'] = array( '#title' => t('Name'), '#type' => 'textfield', '#description' => t('Enter the  name of  your  pet.'), '#default_value' => $user->pet_name,'#maxlength' => 32, '#required' => TRUE, '#size' => 15,'#weight' => 5,
'#autocomplete_path' => 'pet/common_pet_names',);

$form['pet_weight'] = array( '#title' => t('Weight'), '#type' => 'textfield',
'#description' => t('Enter the  weight  of  your  pet  in  kilograms.'), '#field_suffix' => t('kilograms'),
'#default_value' => $user->pet_weight,'#size' => 4, '#weight' => 10,);
This results in the form element shown in Figure  11-11.



Figure 11-11. The text field element

The #field_prefix and  #field_suffix properties are specific to text fields and  place  a string immediately before or after the text
field inputThe #autocomplete property defines a path where Drupals automatically included JavaScript will send HTTP requests using jQuery. In the preceding example, it will query http://example.com/?q=pet/common_pet_names.
See the user_autocomplete() function in modules/user/user.pages.inc for a working example.

Properties commonly used with the text field element follow: #attributes, #autocomplete_path (the default is FALSE), #default_
value, #description #field_prefix, #field_suffix, #maxlength (the default is 128), #prefix, #required, #size (the default is60), 
#suffix, #title, #process (the default iarray('ajax_process_form')), and  #weight.

Password

This element creates an HTML password field, where input entered by the user is not shown (usually bullet characters are echoed
to the screen instead). An example from user_login_block() follows:

$form['pass'] = array('#type' => 'password', '#title' => t('Password'),'#maxlength' => 60, '#size' => 15, '#required' =>
TRUE,);
Properties commonly used with the password element are #attributes, #description, #maxlength#prefix, #required #size
(the default is 60) #suffix, #title, #process (the default is array('ajax_ process_form')), and  #weight. The #default_
value property is not used with the password element for security reasons.

Password with Confirmation

This element creates two HTML password fields and  attaches a validator that checks if the two passwords match. For
example, this element is used by the user module when a user changes his or her password.

$form['account']['pass'] = array( '#type' => 'password_confirm', '#description' =>
t('To change  the  current   user  password,  enter   the  new password in  both  fields.'), '#size' => 25,);

Textarea

An example of the textarea element follows:

$form['pet_habits'] = array( '#title' => t('Habits'), '#type' => 'textarea',
'#description'  => t('Describe  the  habits  of  your pet.'), '#default_value'  => $user->pet_habits,
'#cols'  => 40, '#rows'  => 3, '#resizable'  =>  FALSE, '#weight'  =>  15,);

Properties commonly used with the textarea element are #attributes,  #cols (the default is 60),
#default_value, #description, #prefix, #required, #resizable, #suffix, #title, #rows (the default is 5),
#process (the default is array('ajax_process_form')), and  #weight.
The #cols setting may not be effective  if the dynamic textarea resizer is enabled by settin#resizable to TRUE.

Select

A select  element example from modules/statistics/statistics.admin.inc follows:

$period  = drupal_map_assoc(array(3600,  10800,  21600,  32400,  43200,  86400,  172800, 259200,  604800,  1209600,  2419200,  4838400,  9676800),  'format_interval');
/*  Period  now  looks  like  this: Array  ([3600]  => 1  hour [10800]  => 3  hours [21600]  => 6  hours [32400]  => 9  hours[43200]  => 12  hours [86400]  => 1  day [172800]  => 2  days [259200]  => 3  days [604800]  => 1  week [1209600]  => 2  weeks [2419200]  => 4  weeks [4838400]  => 8 weeks [9676800]  => 16  weeks  )
*/
$form['access']['statistics_flush_accesslog_timer']  = array( '#type'  => 'select',
'#title'  => t('Discard  access logs  older  than'),
'#default_value'  => variable_get('statistics_flush_accesslog_timer',  259200), '#options'  => $period,
'#description'  => t('Older  access log  entries  (including  referrer  statistics) will  be automatically  discarded.  (Requires  a  correctly  configured
<a href="@cron">cron  maintenance  task</a>.)',  array('@cron'  => url('admin/reports/status'))),);
Drupal supports grouping in the selection options by defining the #options property to be an associative array of submenuchoices, as shown in Figure  11-12.

$options = array( array(t('Healthy') => array(1  => t('wagging'),2  => t('upright'),3  => t('no tail')),), array(
t('Unhealthy') => array(4  => t('bleeding'),5  => t('oozing'),),),);
$form['pet_tail'] = array( '#title' => t('Tail demeanor'),
'#type' => 'select','#description' => t('Pick the  closest match that   describes the  tail of  your  pet.'),
'#options' => $options, '#multiple' => FALSE, '#weight' => 20,);


Figure 11-12. A select element using choice grouping


Selection of multiple choices is enabled by setting the #multiple property to TRUE. This also changes the value in $form_state['values'] from a string (e.g., 'pet_tail' = '2', assuming upright is selected in the preceding example) to an array of values (e.g.,pet_tail = array(   1  => '1', 2  => '2') assuming wagging and  upright are both chosen in the preceding
example). Properties commonly used with the select  element are #attributes, #default_value, #description#multiple, #options#prefix, #required, #suffix, #title, #process (the default is array('form_ process_select',
'ajax_process_form')), and  #weight.

Radio Buttons

A radio button example from modules/block/block.admin.inc follows:

$form['user_vis_settings']['custom'] = array( '#type' => 'radios',
'#title' => t('Custom  visibility settings'), '#options' => array(
t('Users  cannot  control whether  or  not  they  see  this block.'), t('Show  this block  by default, but  let  individual users   hide  it.'),t('Hide  this block  by default but  let  individual users   show it.')),
'#description' => t('Allow individual users   to  customize   the  visibility  of this block  in  their account  settings.'),'#default_value' => $edit['custom'],);
Properties commonly used with this element are #attributes, #default_value, #description,#options, #prefix, #required,#suffix, #title, and  #weight. Note that the #process property is set tarray('form_process_radios') (see includes/form.inc) by default.

Check Boxes

An example of the check boxes element follows. The rendered version of this element is shown in Figure 11-13.

$options = array('poison' => t('Sprays deadly  poison'), 'metal' => t('Can   bite/claw through  metal'), 'deadly' => t('Killed  previous owner')  );$form['danger'] = array('#title' => t('Special conditions'), '#type' =>
'checkboxes','#description' => (t('Please note  if any of  these conditions apply  to  your pet.')),
'#options' => $options, '#weight' => 25,);



Figure 11-13. An example using the check boxes element

The array_filter() function is often used in validation an submission functions to get the keys of the checked boxes. Forexample, if the first two check boxes are checked in Figure  11-13, 
$form_state['values']['danger'] would contain the following:
array('poison' => 'poison', 'metal' => 'metal', deadly' => 0,)

Running array_filter($form_state['values']['danger']) results in an array containing only the keys of the checked boxes: array('poison', 'metal').

Properties commonly used with the check boxes element are #attributes, #default_value,
#description, #options, #prefix, #required, #suffix, #title, #tree (the default is TRUE), and  #weight.
Note that the #process property is set to form_process_checkboxes() (see includes/form.inc) by default.

Value

The value element is used to pass values internally from $form to $form_state['values'] without ever being sent  to the browser, for example:

$form['pid'] = array( '#type' => 'value', '#value' => 123,);

When  the form is submitted, $form_state['values']['pid'] will be 123.
Do not confuse #type  => 'value' and  #valu => 123. The first declares what  kind of element is being described, and  the
second declares the value of the element. Only #type and  #value properties may be used with the value element.

Hidden

This element is used to pass a hidden value into a form using  an HTML input field of type hidden, as in the following example.
$form['my_hidden_field'] = array( '#type' => 'hidden','#value' => t('I am  a  hidden  field value'),);

If you want  to send a hidden value along  through the form,  it’s usually a better idea to use the value element for this, and  use
the hidden element only when the value element does not suffice. That’s because the user can view the hidden element in the
HTML source of a web form, but the value element is internal to Drupal and  not included in the HTML. Only the #prefix,
 #suffix, #process (the default is array('ajax_process_form')), and  #value properties are used with the hidden element.

Date

The date  element, as shown in Figure  11-14, is a combination element with three select  boxes:

$form['deadline'] = array( '#title' => t('Deadline'), '#type' => 'date','#description' => t('Set the  deadline.'), '#default_
value' => array('month'  => format_date(time(), 'custom',  'n'), 'day' => format_date(time(), 'custom',  'j'), 'year' => format_date(time(), 'custom',  'Y'),),);

Figure 11-14. A date element

 Properties commonly used by the date  element are #attributes, #default_value, #description#prefix, #required, #suffix, #title, 
and  #weight. The #process property defaults to call array('form_process_date'), in which the year selector is hard-coded to the
years 1900 through 2050. The #element_validate property defaults to date_validate() (bothfunctions can be found in includes/
form.inc). You can define these properties when defining the date  element in your form to use your own code  instead.

Weight

The weight  element (not  to be confused with the #weight property) is a drop-down used to specify weights:

$form['weight'] = array( '#type' => 'weight', '#title' => t('Weight'), '#default_value' => 0, '#delta' => 10,
'#description' => t('In listings, the  heavier vocabularies will  sink  and the lighter  vocabularies will  be  positioned nearer  the  top.'),);
The preceding code  will be rendered as shown in Figure  11-15.


Figure 11-15. The weight element
The #delta property determines the range of weights to choose from and  defaults to 10. For example, if you set #delta to 50, the
range of weights would be from -50 to 50. Properties commonly used with the weight element are #attributes, #delta (the default is 10), #default_value, #description#prefix, #required #suffix, #title, and  #weight. The #process property defaults to array('form_ process_weight', 'ajax_process_form'). 

File Upload

The file element creates a file upload interface. Here’s an example from modules/user/user.module:

$form['picture']['picture_upload'] = array( '#type' => 'file', '#title' => t('Upload picture'), '#size' => 48,
'#description' => t('Your virtual  face   or  picture.'));
The way this element is rendered is shown in Figure  11-16.

Figure 11-16. A file upload element

Note that if you use the file element, you’ll need to set the enctype property at the root of your form:
$form['#attributes']['enctype'] = 'multipart/form-data';
Properties commonly used with the file element are #attributes, #default_value, #description#prefix, #required #size (the
default is 60)#suffix, #title, and  #weight.

Fieldset
A fieldset element is used to group elements together. It can be declared collapsible, which means JavaScript automatically provided byDrupal is used to open and  close the fieldset dynamically with a click while a user is viewing the form. Note the use of the
#access property in this example to allow or deny  access to all fields within the fieldset:

// Node author  information for  administrators.
$form['author'] = array( '#type' => 'fieldset','#access' => user_access('administer nodes'), '#title' =>
t('Authoring information'), '#collapsible' => TRUE,'#collapsed' => TRUE,'#weight' => 20,);

Properties commonly used with the fieldset element are #attributes, #collapsed (the default iFALSE), #collapsible (the default is
FALSE), #description, #prefix, #suffix, #title, #process (the default is array('form_process_fieldset','ajax_process_form')), and  #weight.

Submit

The submit element is used to submit the form. The word displayed inside the button defaults to “Submit” but can be changed using the #value property:

$form['submit'] = array( '#type' => 'submit', '#value' => t('Continue'),);

Properties commonly used with the submit element are #attributes, #button_type (the default i“submit”), #executes_submit_callback (the default is TRUE), #name (the default is “op”), #prefix, #suffix#value, #process (the default is array('ajax_process_
form')), and  #weightAdditionally, the #validate and  #submit properties may be assigned directly to the submit element. For
example, if #submit is set to array('my_special_form_submit'), the function my_special_form_submit() will be used instead of
the forms definedsubmit handler(s).

Button

The button element is the same as the submit element except that the #executes_submit_callback property defaults to FALSE. This property tells Drupal whether to process the form (when TRUE) or simply re-render the form (if FALSE). Like the Submitbutton,
specific validation and  submit functions can be assigned directly to a button. 

Image Button

The image button element is the same as the submit element with two exceptions. First, it has a #src property that has the URL of
an image as its value. Secondly, it sets the internal form property #has_garbage_value to TRUE, which prevents #default_value
from being used due to a bug in Microsoft Internet Explorer. Do not use #default_value with image buttons. Here is an image
button that uses the built-in Powered by Drupal image as the button:

$form['my_image_button'] = array( '#type' => 'image_button', '#src' => 'misc/powered-blue-80x15.png','#value' => 'foo',);

The value of the button can be safely retrieved by looking i$form_state['clicked_button']['#value'].

Markup

The markup element is the default element type if no #type property has been used. It is used to introduce text or HTML into the middle of a form.

$form['disclaimer'] = array( '#prefix' => '<div>', '#markup' => t('The  information below  is entirely optional.'),
'#suffix' => '</div>',);

Properties commonly used with the markup element are #attributes, #prefix (the default is the empty string ''), #suffix (the default is the empty string ''), #value, and  #weight.

Item

The item  element is formatted in the same way as other input element types  like text element or select element, but it lacks the
input field.
$form['removed'] = array( '#title' => t('Shoe size'), '#type' => 'item', '#description' => t('This  question has  been  removedbecause  the  law  prohibits  us from asking  your  shoe  size.'),);
The preceding element is rendered as shown in Figure  11-17.


Figure 11-17. An item element

 Properties commonly used with the item  element are #attributes, #description, #prefix (the default is an empty string, '')
#required, #suffix (the default is an empty string, ''),  #title, #value, an#weight.

#ajax Property

AJAX-enabled forms  in Drupal provide the ability to dynamically modify forms as a user interacts with the elements on the form.
A common example is to update the list of items in a select  list based on some value that the user selected or entered in aprevious
field  for example, select  an automobile manufacturer from a select  list changes the list of available models based on the value
selected by the user.  While you can perform that action without AJAX, its nice to not force the user  to sit through a pagereload
the form populates the values  in the second drop down list.  AJAX provides the means for performing that update without having to reload the whole  page,  only the part  that needs to be changed. The benefits of using the Form  API’s AJAX capbilitiesinclude:
     AJAX forms provide dynamic form behavior withouforcing  the user  to sit through one or more page reloads while the form updates an element.

     You as the developer don't have to code  Javascript to create an AJAX-enabled form. The Form  API does 
all of the heavy lifting for you.

     AJAX forms  are often simpler than multistep forms.

The process for creating an AJAX-enabled form is relatively simple:
Create or update an existing form element and  mark  it as AJAX-enabled by using the #ajax property.
Form  elements marked as AJAX-enabled trigge a background AJAX call when the user change it or clicks on it.
The #ajax['wrapper'] property includes the HTML ID of a page section that will be modified when the Ajax call is executed. The
#ajax['callback'] indicates which callback should be executed after the AJAX call happens and  the form is rebuilt.
 Second, create a callback function using the name of the callback listed  i#ajax['callback']. This function’s primary typically
updates the content of the HTML ID identified in the #ajax[‘wrapper].

The following example demonstrates the use of Ajax by creating a form with two select  lists, one for automobile manufacturer and the second for the models offered by that manufacturer. When  a user selects a manufacturer from the list, the second select list is
automatically updated with the list of models that are offered by the manufacturer that was selected by the user. The second select
list is updated through Ajax without having to reload the page.   Only that section of the page that contains thmodel select  list is
updated.
 /**
*    form with  a  dropdown  whose options are  dependent  on a
*   choice made in  a  previous dropdown.
*
*   On  changing  the  first dropdown, the  options in  the  second
*   are  updated.
*/
function automobile_dependent_dropdown($form,  &$form_state)  {
// get  the  list of  manufacturers  to  populate   the  manuacturer dropdown
$options_first = _automobile_get_manufacturer_dropdown_options();
// if we have  a  value  for  the  manufacturer  dropdown  from
// $form_state['values'] we use  this both  as  the  default value  for
// the  first dropdown  and also as  a  parameter  to  pass  to  the
// function that   retrieves the  options for  the  second  dropdown.
$selected = isset($form_state['values']['manufacturer_dropdown']) ?
$form_state['values']['manufacturer_dropdown'] : key($options_first);
$form['manufacturer_dropdown']   = array( '#type' => 'select',
'#title' => 'Manufacturer', '#options' => $options_first, '#default_value' => $selected,
// bind  an ajax  callback to  the  change  event  (which  is the  default for  the
// select form type) of  the  manufacturer  dropdown. It  will replace the
// model dropdown  when rebuilt '#ajax' => array(
'callback' => 'automobile_dependent_dropdown_callback', 'wrapper'   => 'dropdown_model_replace',
),
);

$form['model_dropdown']  = array( '#type' => 'select',
'#title' => 'Model',
// The entire enclosing div  created here  gets  replaced when manufacturer_dropdown
// is changed.
'#prefix' => '<div  id="dropdown_model_replace">', '#suffix' => '</div>',
// when the  form is rebuilt during  ajax  processing, the  $selected  variable
// will now have  the  new value  and so  the  models  will change '#options' => _automobile_get_model_dropdown_options($selected), '#default_value' => isset($form_state['values']['model_dropdown']) ?$form_state['values']['model_dropdown']  : '',
);
$form['submit']  = array( '#type'  => 'submit', '#value'  => t('Submit'),
);

return  $form;
}
if (isset($options[$key])) { return  $options[$key];
}
else {
return  array();
}
}

The general processing performed by the code  above:

1.       Presents the form to the user,  as any form would be.

2.       In the form, a div with an HTML ID of ' dropdown_model_replace ' wraps
$form['model_dropdown']  . This is done with $form['model_dropdown'] ['#prefix'] and  $form['model_dropdown']  ['#suffix'].

3.       When  the user changes $form['manufacturer_dropdown']   a background request is made to the server,  causing the form to be rebuilt.

4.       The form is rebuilt and  the values for model are reset based on the value selected in the $form[‘model_dropdown’]

5.       The function   automobile_dependent_dropdown_callback() is called.  It selects the piece  of the form which is to be replaced on the page (almost always the same as what's in #ajax['wrapper']).

6.       The portion returned is rendered, sent  back to the page,  and  the div with id ‘dropdown_model_replace’ is replaced on the page.

/**
*   Selects  just  the  model  dropdown  to  be returned  for  re-rendering
*
*   The  version  here  has been re-loaded  with  a  different  set of  options  and
*   is sent  back to  the  page to  be updated.
*
*   @return  renderable  array  (the  second dropdown)
*/
function  automobile_dependent_dropdown_callback($form,  $form_state)  { return  $form['model_dropdown'];
}


/**
*   Helper  function  to  populate  the  manufacturer  dropdown.  This  would  normally  be
*   pulling  data  from  the  database.
*
*   @return  array  of  options
*/
function  _automobile_get_manufacturer_dropdown_options()  {
// drupal_map_assoc()  just  makes  an array('Strings'  => 'Strings'...).
return  drupal_map_assoc(array(t('Honda'),  t('Toyota'),  t('Ford'),  t('Volkswagen')));
}

/**
*   Helper  function  to  populate  the  model  dropdown.  This  would  normally  be
*   pulling  data  from  the  database.
*
*   @param  key.  This  will  determine  which  set of  options  is returned.
*
*   @return  array  of  options
*/
function  _automobile_get_model_dropdown_options($key  = '') {
$options  = array(
t('Honda')  => drupal_map_assoc(array(t('Accord'),  t('Civic'),  t('CRX'),  t('Pilot'))), t('Toyota')  => drupal_map_assoc(array(t('Camry'),  t('Yaris'),  t('Tundra'),
t('Tacoma'))),
t('Ford')  => drupal_map_assoc(array(t('F-150'),  t('Explorer'),  t('Escape'),  t('Edge'))), t('Volkswagen')  => drupal_map_assoc(array(t('GTI'),  t('Passat'),  t('Jeta'),  t('Polo'))),
);
Remember that the $form  you're dealing with in your callback function has already been sent through all the form processing functions (but hasn't yet been sent to drupal_render()). So while adjusting, say, themarkup of an element is straightforward:

<?php
$elements['some_element']['#markup'] = 'New markup.'; return  $elements;
?>





Changing a value that has already been converted into the #attributes property means digging deeper into the $form  array, as well as also changing that element's corresponding property.

<?php
// You need  to  do both
$elements['some_element']['#disabled'] = TRUE;
$elements['some_element']['#attributes']['disabled'] = 'disabled'; return  $elements;
?>


If Javascript is not supported

Best practices call for providing a graceful for degrading behavior when the users browser does not support Javascript.  AJAX forms provide the ability to address this, but it may take considerable effort to make a form behave correctly in either a Javascript ornon-javascript environment. In most cases you must provide alternative means for navigating, such as a "next" button for the AJAX-enabled element. When  it is pressed, the page (and form) are rebuilt emulating the same functionality when the AJAX- enabledelement is changed, but with a page reload. The Examples module provides several examples of AJAX with graceful degradation in ajax_example_graceful_degradation.inc:

     An add-more button

     A dependent dropdown example

     Dynamic sections

     Wizard (classic  multistep form)


Additional AJAX features

The AJAX Framework provides many additional features and  options in beyond basic forms behavior.

     AJAX Framework Commands may be used on the server  side to generate dynamic behaviors on the page.  The #ajax['callback'] function may return an array of commands instead of returning a renderable array or an HTML string. Thisprovides the ablity to create dynamic functions that extend beyond simple Form API operations.

     The #ajax['callback'] does  not have to return a portion of the form. It can return any renderable array,  or it can return an HTML string.

     The replace method is the default and  most common, but it is also possible to do other things with the content returned by the #ajax['callback'], including prepending, appending, etc.

     If you want  to replace ajax_form_callback() with your own functions, use ajax_form_callback() would be the model for your replacement. In that case, you would change #ajax['path'] from the default 'system/ajax' and  set up a menu entryin hook_menu() to point to your replacement path.





Additional resources

     The Examples module (http://drupal.org/project/examples) provides more examples, including an AJAX-enabled dependent dropdown, and  several other examples, including an example of graceful degradation when Javascript is notenabled.

     See the AJAX Framework (http://api.drupal.org/api/group/ajax/7) documentation and  the Form  API Reference


Summary


After reading this chapter, you should understand the following concepts:

     How the form API works.

     Creating simple forms.

     Changing the rendered form using theme functions.

     Writing  a validation function for a form or for individual elements.

     Writing  a submit function and  doing redirection after form processing.

     Altering existing forms.

     Creating dynamic forms.

     Using the #ajax property to create dynamic forms  that react to users input without page reloads

     The form definition properties you can use and  what  they mean.

     The form elements (text fields, select  fields, radios, and  so on) thatre available in Drupal.

     How AJ-based  text replacement works with forms.

For more information about forms, including tips and  tricks, see the Drupal Handbook at


Không có nhận xét nào:

Đăng nhận xét