Drupal 7中的条件字段组/字段集

Drupal 7中的条件字段组/字段集

问题描述:

Background: In Drupal 7, I have created a form with CCK (aka the Field UI). I used the Field group module to create a fieldgroup, but I need it to be conditional, meaning it will only display depending on a previous answer.

Previous research: To create a conditional field, you can use hook_form_alter() to edit the #states attribute like so:

function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'person_info_node_form') {
    // Display 'field_maiden_name' only if married
    $form['field_maiden_name']['#states'] = array(
      'visible' => array(
        ':input[name="field_married[und]"]' => array('value' => 'Yes'),
      ),
    );
  }
}

However, there seems to be no way to use the States API for fieldgroups. One thing to note is that, while fields are stored in $form, fieldgroups are stored in $form['#groups'] as well as in $form['#fieldgroups']. I don't know how to distinguish between these, and with this in mind, I have tried to apply a #states attribute to a fieldgroup in the same manner as above. However, it only produces server errors.

Question: Is there a way to make a fieldgroup display conditionally using the States API or some alternative approach?

Here's the simplest solution I came up with. There are essentially 2 parts to this: (1.) programmatically alter the display of the form, and (2.) use the GUI to alter the display of the content.

(1.) First, I used hook_form_alter() to programmatically create the conditional fieldset and add existing fields to it. The code is shown below.

function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'FORM_ID_node_form') {
    // programmatically create a conditional fieldset
    $form['MYFIELDSET'] = array( // do NOT name the same as a 'Field group' fieldset or problems will occur
      '#type' => 'fieldset',
      '#title' => t('Conditional fieldset'),
      '#weight' => intval($form['field_PARENT']['#weight'])+1, // put this fieldset right after it's "parent" field
      '#states' => array(
        'visible' => array(
          ':input[name="field_PARENT[und]"]' => array('value' => 'Yes'), // only show if field_PARENT == 'Yes'
        ),  
      ),  
    );

    // add existing fields (created with the Field UI) to the
    // conditional fieldset
    $fields = array('field_MYFIELD1', 'field_MYFIELD2', 'field_MYFIELD3');
    $form = MYMODULE_addToFieldset($form, 'MYFIELDSET', $fields);
  }
}

/**
 * Adds existing fields to the specified fieldset.
 *
 * @param  array   $form Nested array of form elements that comprise the form.
 * @param  string  $fieldset The machine name of the fieldset.
 * @param  array   $fields An array of the machine names of all fields to
 *                   be included in the fieldset.
 * @return array   $form The updated form.
 */
function MYMODULE_addToFieldSet($form, $fieldset, $fields) {
  foreach($fields as $field) {
    $form[$fieldset][$field] = $form[$field]; // copy existing field into fieldset
    unset($form[$field]); // destroy the original field or duplication will occur
  }

  return $form;
}

(2.) Then I used the Field group module to alter the display of the content. I did this by going to my content type and using the 'Manage display' tab to create a field group and add my fields to it. This way, the fields will appear to be apart of the same group on both the form and the saved content.

Maybe you can try to look at the code of this module to help you find an idea.

you have to use the hook_field_group_build_pre_render_alter()

Simply :

function your_module_field_group_build_pre_render_alter(&$element) {
  $element['your_field_group']['#states'] = array(
    'visible' => array(
      ':input[name="field_checkbox"]' => array('checked' => TRUE),
    ),
  );
}

This works perfecly. If the group A is in an another group, do this

$element['groupA']['groupB']['#states'] etc....

You may need to add an id attribute if none exists:

$element['your_field_group']['#attributes']['id'] = 'some-id';
$element['yout_field_group']['#id'] = 'some-id';