It's probably working as designed but not always as logical to me. When checkbox B will get checked when checkbox A is checked, it doesn't matter if it has a default value 'checked'. It will always be overridden by javascript and be unchecked at page load because checkbox A is unchecked.

Example:

$form['checkbox_a'] = array(
  '#type' => 'checkbox',
  '#title' => t('Checkbox A'),
);
$form['checkbox_b'] = array(
  '#type' => 'checkbox',
  '#title' => t('Checkbox B'),
  '#default_value' => 1, // This one gets overridden at page load due to the #states.
  '#states' => array(
    'checked' => array(
      ':input[name="checkbox_a"]' => array('checked' => TRUE),
    ),
  ),
);

As you can see, 'checkbox B' has a default value of 1 (checked), but it will never be checked when the page gets loaded (well, for a millisecond it does) because it's depending on 'checkbox A' through javascript. Though, 'checkbox B' can be manually clicked and checked independently from 'checkbox A', which is good. But at page load, the #states override the default value.

My question: is there a way in the form API to avoid this, so the default value doesn't get undone. Apart from writing the javascript ourselves because that would make the form states useless.

CommentFileSizeAuthor
#5 drupal_checkboxes2.gif1.45 MBjimafisk

Comments

fernly’s picture

Issue summary: View changes
fernly’s picture

Issue summary: View changes
cilefen’s picture

Does the 'touched' state work? If it did, you could try something like:

'#states' => array(
    'checked' => array(
      ':input[name="checkbox_a"]' => array('checked' => TRUE),
      ':input[name="checkbox_a"]' => array('touched' => TRUE),
    ),
  ),
fernly’s picture

Unfortunately not working, but thanks for the suggestion.

jimafisk’s picture

StatusFileSize
new1.45 MB

I ran into this issue as well on an Entity Reference field (taxonomy for Neighborhoods in my case). I was able to get around it with the addition of an 'unchecked' state as shown below.

For some additional context about why the code is written the way it is below, I also ran into a problem where the the 'checked' state wasn't being applied to the correct HTML element (see https://www.drupal.org/node/994360#comment-5860156), so I needed to loop through the checkbox options individually and apply the state to each option that way.

// The $citywide_input variable is the 'name' attribute for my checkbox that controls the other checkboxes.
// I removed the code showing how the $citywide_tid was obtained because it's not important here.
// You should use the 'name' attribute for your controlling checkbox (you can inspect element in your browser to find this).
$citywide_input = "field_multiple_neighborhoods[und][$citywide_tid]";
// Loop through every Neighborhood checkbox, in my case the controlling checkbox and
// the dependent checkboxes both belong to the same field: field_multiple_neighborhoods.                                                   
foreach ($form['field_multiple_neighborhoods'][LANGUAGE_NONE]['#options'] as $tid => $name) {
  // Set the state for each checkbox option individually.                                              
  $form['field_multiple_neighborhoods'][LANGUAGE_NONE][$tid]['#states'] = array(                     
    // Check/uncheck all checkboxes based on 'Citywide' value.                                       
    'checked' => array(                                                                              
      ':input[name="' . $citywide_input . '"]' => array('checked' => TRUE),                          
    ),                                                                                               
    // THIS IS THE IMPORTANT PART!
    // Allow the already enabled checkboxes (default values) to be checked on page load.                                  
    'unchecked' => array(                                                                            
      ':input[name="field_multiple_neighborhoods[und][' . $tid . ']"]' => array('checked' => FALSE), 
    ),                                                                                               
  );                                                                                                 
}                                                                                                    

The trick is to tell Drupal to uncheck the boxes only if they're already unchecked. Since the default values load as checked, it shouldn't uncheck them. Strangely from there, the controlling checkbox can enable/disable all boxes, which is exactly what I wanted (see attached gif to see it in action).

Version: 7.36 » 7.x-dev

Core issues are now filed against the dev versions where changes will be made. Document the specific release you are using in your issue comment. More information about choosing a version.

Status: Active » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.