25

How can I have multiple values trigger the Form API's #states?

Say for example, I wanted this field to be visible not only if the value is 5 (currently works below), but wanted to make the field visible if the the values are 3, 4 or 5.

'#states' => array(
    'visible' => array(
       ':input[name="field_star_rating"]' => array('value' => t('5')),
    ),
),

As a note, I tried the following and it does not work. It only works if the value is '4'

'#states' => array(
    'visible' => array(
        ':input[name="field_star_rating"]' => array('value' => t('5')),
        ':input[name="field_star_rating"]' => array('value' => t('4')),
    ),
),

This also does not work, it too only works if the value is '4':

'#states' => array(
    'visible' => array(
        ':input[name="field_star_rating"]' => array('value' => t('5'), 'value' => t('4')),
    ),
),

3 Answers 3

60
+50

Here's what you need:

'#states' => array(
    'visible' => array(
        ':input[name="field_star_rating"]' => array(
            array('value' => t('5')),
            array('value' => t('4'))
        ),
    ),
),
5
  • This is indeed the correct way, the current one marked as correct is wrong. See this issue for more info: drupal.org/node/735528
    – Robin
    Jan 3, 2013 at 4:52
  • The #states API sure has come a long way sense 2011. Marking as correct.
    – Citricguy
    Feb 6, 2014 at 1:51
  • this is a great answer, and I came here from Google, like a dozen times... a bounty is on its way.
    – AKS
    Mar 27, 2015 at 3:41
  • It is working fine for normal view. After running any 'ajax', it added again and again
    – Guru
    Nov 23, 2015 at 11:10
  • In my case with hook_form_alter of an existing node form the states only changed correctly when i added [und] to the name: input[name="field_star_rating[und]"]' => array(
    – user24957
    Jul 27, 2020 at 9:42
3

Only way I could figure is to use #ajax in D7.

Here are a few helpful tip's I wish I would have known before starting.

  1. #ajax in the form API is awesome and worth learning
  2. #states does not support OR or XOR (Without a patch? http://drupal.org/node/735528 )
  3. dpm($form); and var_dump($form_state) on a custom submit function are priceless

Here is a modified version of one of the AJAX examples from the examples module.

function plugin_autotextfields($form, &$form_state) {

    $form['star_rating'] = array(
        '#type' => 'select',
        '#title' => t('Star Rating'),
        '#options' => array('_none' => '- select -', 5 => '5 Star', 4 => '4 Star', 3 => '3 Star', 2 => '2 Star', 1 => '1 Star'),
        '#ajax' => array(
            'callback' => 'plugin_autotextfields_callback',
            'wrapper' => 'textfields',
            'effect' => 'fade',
        ),
    );

    $form['textfields'] = array(
        '#title' => t("Fieldset Name"),
        '#prefix' => '<div id="textfields">',
        '#suffix' => '</div>',
        '#type' => 'fieldset',
        '#description' => t('Where the field will be placed'),
    );

    if (!empty($form_state['values']['star_rating']) && $form_state['values']['star_rating'] == 5) {
        $form['textfields']['review'] = array(
            '#type' => 'textfield',
            '#title' => t('Message if 5 stars'),
        );
    } else if (!empty($form_state['values']['star_rating'])) {
        $form['textfields']['review'] = array(
            '#type' => 'textfield',
            '#title' => t('Message if not 5 stars'),
        );
    }

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

    return $form;
}

function omfg_autotextfields_callback($form, $form_state) {
    return $form['textfields'];
}

I hope this helps someone that runs into the same problem :)

1
  • Wow! Very helpful answer my friend. I have been wrapping my head around an issue with #states and now have it working but #ajax would of obviously been easier now that you slapped me with a clue-stick. And that debugging tip as a bonus? Sorry I have to pay you with measly karma. ;) Apr 24, 2012 at 8:28
3
 $form['student_type'] = array(
    '#type' => 'checkboxes',
    '#options' => array(
      'high_school'   => t('High School'),
      'undergraduate' => t('Undergraduate'),
      'graduate'      => t('Graduate'),
    ),
    '#title' => t('What type of student are you?')
  );

// High school information.
  $form['high_school']['tests_taken'] = array(
    '#type' => 'textfield',
    '#title' => t('What standardized tests did you take?'),
    '#states' => array(
      'visible' => array(   // action to take.
        ':input[name="student_type[high_school]"]' => array('checked' => TRUE),
        ':input[name="student_type[undergraduate]"]' => array('checked' => TRUE),
        ':input[name="student_type[graduate]"]' => array('checked' => FALSE),
      ),
    ),
  );

P.S. See the examples module for more features "form_example/form_example_states.inc"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.