Download & Extend

States fail when using integer values for select/radio dependencies

Project:Drupal core
Version:7.x-dev
Component:forms system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:closed (fixed)
Issue tags:needs backport to D7

Issue Summary

When using integer options for select and radio form fields, the states system fails for dependent form fields operating with integer values.

For example:

<?php
define
('OPTION_1', 1);
define('OPTION_2', 2);

function
example_form(&$form, $form_state) {
 
$form['select'] = array(
   
'#type' => 'select',
   
'#options' => array(
     
OPTION_1 => 'Option 1',
     
OPTION_2 => 'Option 2',
    ),
  );

 
$form['dependent_field'] = array(
   
'#type' => 'text',
   
'#states' => array(
     
'visible' => array(
       
':input[select]' => array('value' => OPTION_1)
      ),
    ),
  );
}
?>

Fails because $(':input[select]').val() == '1' not 1, and the states system checks to make sure the values are the same type. The way around it is to type cast the dependent_field state value as a string:

<?php
  $form
['dependent_field'] = array(
   
'#type' => 'text',
   
'#states' => array(
     
'visible' => array(
       
':input[select]' => array('value' => (string) OPTION_1)
      ),
    ),
  );
?>

but is there a better way to approach this? It's not exactly intuitive to make the value a string.

Comments

#1

#2

#3

Probably not - this bug is most likely caused by PHP integer to JSON conversion (i.e., when #states get converted into Drupal.settings).

#4

Subscribe

#5

Version:7.x-dev» 8.x-dev
Status:active» needs review

Attached is a patch against the 8.x branch to resolve this issue by altering the value comparison code in states.js.

With this patch, if the reference value (from the #states array) is numeric but the value from jQuery is a string, then the reference variable is cast as a string before the strict comparison in compare().

AttachmentSizeStatusTest resultOperations
drupal-879580-5-fix_states_integer_values.patch475 bytesIdlePASSED: [[SimpleTest]]: [MySQL] 33,573 pass(es).View details

#6

Status:needs review» reviewed & tested by the community

Looks clean and solves the problem for me. Thank you arithmetric.

#7

Status:reviewed & tested by the community» needs review

Looks good. Wondering whether we could capture this non-obvious edge-case in an inline comment, to prevent people from interpreting this data type casting from number to string as a bug, and clarify what the casting is actually fixing, in case someone wants to rewrite/revamp this code at some point in the future.

#8

@sun: Thanks for the feedback. I've updated the patch to include a comment on why the type casting should happen in this case.

AttachmentSizeStatusTest resultOperations
drupal-879580-8-fix_states_integer_values.patch755 bytesIdlePASSED: [[SimpleTest]]: [MySQL] 33,635 pass(es).View details

#9

Status:needs review» reviewed & tested by the community

Thanks!

#10

Will this also be fixed for D7? The patch applies and works for 7.x.

#11

Issue tags:+needs backport to D7

Changing to the "official" form of the backport tag.

#12

Version:8.x-dev» 7.x-dev

Committed to 8.x, moving to 7.x for webchick.

#13

Status:reviewed & tested by the community» fixed

Committed and pushed to 7.x. Thanks!

#14

Status:fixed» closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

nobody click here