hook_field_widget_form

7 field.api.php hook_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element)
8 field.api.php hook_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element)

Return the form for a single field widget.

Field widget form elements should be based on the passed-in $element, which contains the base form element properties derived from the field configuration.

Field API will set the weight, field name and delta values for each form element. If there are multiple values for this field, the Field API will invoke this hook as many times as needed.

Note that, depending on the context in which the widget is being included (regular entity form, field configuration form, advanced search form...), the values for $field and $instance might be different from the "official" definitions returned by field_info_field() and field_info_instance(). Examples: mono-value widget even if the field is multi-valued, non-required widget even if the field is 'required'...

Therefore, the FAPI element callbacks (such as #process, #element_validate, #value_callback...) used by the widget cannot use the field_info_field() or field_info_instance() functions to retrieve the $field or $instance definitions they should operate on. The field_widget_field() and field_widget_instance() functions should be used instead to fetch the current working definitions from $form_state, where Field API stores them.

Alternatively, hook_field_widget_form() can extract the needed specific properties from $field and $instance and set them as ad-hoc $element['#custom'] properties, for later use by its element callbacks.

Other modules may alter the form element provided by this function using hook_field_widget_form_alter().

Parameters

$form: The form structure where widgets are being attached to. This might be a full form structure, or a sub-element of a larger form.

$form_state: An associative array containing the current state of the form.

$field: The field structure.

$instance: The field instance.

$langcode: The language associated with $items.

$items: Array of default values for this field.

$delta: The order of this item in the array of subelements (0, 1, 2, etc).

$element: A form element array containing basic properties for the widget:

  • #entity_type: The name of the entity the field is attached to.
  • #bundle: The name of the field bundle the field is contained in.
  • #field_name: The name of the field.
  • #language: The language the field is being edited in.
  • #field_parents: The 'parents' space for the field in the form. Most widgets can simply overlook this property. This identifies the location where the field values are placed within $form_state['values'], and is used to access processing information for the field through the field_form_get_state() and field_form_set_state() functions.
  • #columns: A list of field storage columns of the field.
  • #title: The sanitized element label for the field instance, ready for output.
  • #description: The sanitized element description for the field instance, ready for output.
  • #required: A Boolean indicating whether the element value is required; for required multiple value fields, only the first widget's values are required.
  • #delta: The order of this item in the array of subelements; see $delta above.

Return value

The form elements for a single widget for this field.

See also

field_widget_field()

field_widget_instance()

hook_field_widget_form_alter()

hook_field_widget_WIDGET_TYPE_form_alter()

Related topics

7 functions implement hook_field_widget_form()

File

modules/field/field.api.php, line 867

Code

function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $element += array(
    '#type' => $instance['widget']['type'], 
    '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
  );
  return $element;
}

Comments

Is Correct?

Is it correct way of using several elements in a single widget?

function my_module_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$element += array(
'#type' => 'fieldset',
'#tree' => true
);
$element['first'] = array(
'#type' => 'textfield',
'#tree' => true
);
$element['second'] = array(
'#type' => 'textfield',
'#tree' => true
);
$element['third'] = array(
'#type' => 'textfield',
'#tree' => true
);
return $element;
}

Where "first", "second" and "third" are names of columns to store the values (from my_module.install).

Multi-value Widget

Here's what I've done and it seems to work:

function my_module_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  return array(
    'value' => $element + array(
      '#type' => 'select',
      '#default_value' => $value,
      '#options' => $options,     
    ),
    'units' => $element + array('#type' => 'value', '#value' => $units),
  );
}

Best Way

Well, my example works too. But this is not enough. Which way is more Drupal, correct, stable, standard?

Can you post your

Can you post your my_module.install code? I am having lots of trouble getting multiple fields to save in the database and think I have incorrectly set up the install file.

I was looking for this too.

I was looking for this, too. He seams to be doing something similar in http://drupalcode.org/sandbox/aklump/1188184.git/tree/refs/heads/7.x-1.x.

NOTE!!!

If you plan on creating a custom field, which also has an alternate widget type of "options_select", or "options_buttons", and you don't override the default form hooks, you absolutely MUST implement:
hook_field_options_list() or your options list will always appear empty.

Here's a handy link to the full reference...

... where you'll find complete lists of available #types of element etc etc, along with all the appropriate attributes for each: forms_api_reference.html

$items empty or not as expected?

It seems $items really does only ever contain the default values for your field.

If you want to manipulate or test the actual values for the actual items in your actual fields, it seems you have to use either hook_widget_form_alter or set up a pre_render callback function

CORRECTION - I should have said hook_field_widget_form_alter not hook_widget_form_alter

jquery with widget forms

Using jquery with hook_field_widget_form doesn't act the same as with the form api. I define a child element with a class of 'example_button' in the widget form but jquery can't seem to find it based on $('input.example_button'). How do I get jquery to recognize DOM elements in the widget form? What am I missing?

Fields order

I'm getting confuse about the elements order: Ideally, I want to have the following sequence:
Item - Description - Price - Currency - Qty - Unit

But to get this order while editing a node, I have to put the elements in a very strange order in my code:

function my_module_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $base = $element;

    $element['price'] = array(
      '#type' => 'textfield',
      '#title' => t('Price'),
      '#default_value' => isset($items[$delta]['price']) ? $items[$delta]['price'] : NULL,
    ) + $base;
    $element['units'] = array(
      '#type' => 'select',
      '#title' => t('Unit'),
      '#default_value' => isset($items[$delta]['units']) ? $items[$delta]['units'] : NULL,
      '#options' => bistrobar_units(),
    ) + $base;
    $element['quantity'] = array(
      '#type' => 'textfield',
      '#title' => t('Qty'),
      '#default_value' => isset($items[$delta]['quantity']) ? $items[$delta]['quantity'] : NULL,
    ) + $base;
    $element['currencies'] = array(
      '#type' => 'select',
      '#title' => t('Currency'),
      '#default_value' => isset($items[$delta]['currencies']) ? $items[$delta]['currencies'] : NULL,
      '#options' => bistrobar_price_currencies(),
    ) + $base;
    $element['menuitem'] = array(
      '#type' => 'textfield',
      '#title' => t('Item'),
      '#default_value' => isset($items[$delta]['menuitem']) ? $items[$delta]['menuitem'] : NULL,
    ) + $base;
    $element['description'] = array(
      '#type' => 'textarea',
      '#title' => t('Description'),
      '#default_value' => isset($items[$delta]['description']) ? $items[$delta]['description'] : NULL,
    ) + $base;
 
  return $element;
}

And of course this is messing up the ideal order when editing the 'content type'.

As this is my first module, I would be glad to get some more understanding about this. Please also tell me if there is a better place to ask such question.

Thanks a lot.

Login or register to post comments