How to reproduce the bug:
1. Create content type with select nodereference component using with example options (set as required!).
2. Create content using this type and select some values.
3. Edit this content.
4. Before Updating the content, please set component to read-only (disabled).
I.E. using the Firebug in Firefox, you can run from console:
$x('//*[@class="form-select required"]')[0].disabled=true
to disable it.
You can't update when component is read-only, because it not passing the reference validation.

There is an error:
This post can't be referenced.

Explanation:
When you have read-only component, it's not submitting value via _POST, it's getting it's default value (copying #default_value to #value).
Difference between normal select and nodereference select is that you receiving an array instead of string (no matter if it's multiple or not)

nodereference.module
function nodereference_widget()
...
      case 'prepare form values':
	$items_transposed = content_transpose_array_rows_cols($items);
	$items['default nids'] = $items_transposed['nid'];

So this array is copied in form_builder() to #value
Later in nodereference_field() function (nodereference.module) you checking if array exists in array instead of string in array, so it's returning FALSE instead of TRUE.

    2.5333   10116848     +648                                   -> in_array(array (0 => '7'), array (0 => 5, 1 => 6, 2 => 7, 3 => 8, 4 => 3)) C:\Users\bronek\workspace\websites\drupal57\modules\cck\nodereference.module:121
                                                                 >=> FALSE

Even if pass this validation, you will have other problems during update the node using the array on non-multiple select.

CommentFileSizeAuthor
#4 nodereference.module.patch789 byteskenorb
#1 Clipboard01.jpg81.62 KBkenorb

Comments

kenorb’s picture

StatusFileSize
new81.62 KB

See attachment.

kenorb’s picture

It's similar problem also with multi-select component (without nodereference) and checkboxes.
For multi-select issue there is a patch here: http://drupal.org/node/236672

kenorb’s picture

Trace of using array instead of string during update the field:

    7.2965   10190872       +0                                 -> db_query('UPDATE {content_type_test_ref_content} SET field_ref2_nid = %d WHERE vid = %d AND nid = %d', array (0 => array (0 => '5'), 1 => '7', 2 => '7')) C:\Users\bronek\workspace\websites\drupal-test\sites\all\modules\cck\content.module:479
    7.2972   10191360     +488                                   -> func_get_args() C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:193
                                                                 >=> array (0 => 'UPDATE {content_type_test_ref_content} SET field_ref2_nid = %d WHERE vid = %d AND nid = %d', 1 => array (0 => array (0 => '5'), 1 => '7', 2 => '7'))
    7.2973   10191976     +616                                   -> array_shift(array (0 => 'UPDATE {content_type_test_ref_content} SET field_ref2_nid = %d WHERE vid = %d AND nid = %d', 1 => array (0 => array (0 => '5'), 1 => '7', 2 => '7'))) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:194
                                                                 >=> 'UPDATE {content_type_test_ref_content} SET field_ref2_nid = %d WHERE vid = %d AND nid = %d'
    7.2975   10191832     -144                                   -> db_prefix_tables('UPDATE {content_type_test_ref_content} SET field_ref2_nid = %d WHERE vid = %d AND nid = %d') C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:195
    7.2975   10192808     +976                                     -> is_array('') C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:62
                                                                   >=> FALSE
    7.2976   10193040     +232                                     -> strtr('UPDATE {content_type_test_ref_content} SET field_ref2_nid = %d WHERE vid = %d AND nid = %d', array ('{' => '', '}' => '')) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:79
                                                                   >=> 'UPDATE content_type_test_ref_content SET field_ref2_nid = %d WHERE vid = %d AND nid = %d'
                                                                 >=> 'UPDATE content_type_test_ref_content SET field_ref2_nid = %d WHERE vid = %d AND nid = %d'
    7.2978   10192088     -952                                   -> is_array(array (0 => array (0 => '5'), 1 => '7', 2 => '7')) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:196
                                                                 >=> TRUE
    7.2979   10191928     -160                                   -> _db_query_callback(array (0 => array (0 => '5'), 1 => '7', 2 => '7'), TRUE) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:199
                                                                 >=> NULL
    7.2980   10192120     +192                                   -> preg_replace_callback('/(%d|%s|%%|%f|%b)/', '_db_query_callback', 'UPDATE content_type_test_ref_content SET field_ref2_nid = %d WHERE vid = %d AND nid = %d') C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:200
    7.2981   10192576     +456                                     -> _db_query_callback(array (0 => '%d', 1 => '%d'), ???) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:0
    7.2982   10193096     +520                                       -> array_shift(array (0 => array (0 => '5'), 1 => '7', 2 => '7')) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:151
                                                                     >=> array (0 => '5')
                                                                   >=> 1
    7.2983   10192616     -480                                     -> _db_query_callback(array (0 => '%d', 1 => '%d'), ???) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:0
    7.2984   10193080     +464                                       -> array_shift(array (0 => '7', 1 => '7')) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:151
                                                                     >=> '7'
                                                                   >=> 7
    7.2985   10192520     -560                                     -> _db_query_callback(array (0 => '%d', 1 => '%d'), ???) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:0
    7.2986   10192984     +464                                       -> array_shift(array (0 => '7')) C:\Users\bronek\workspace\websites\drupal-test\includes\database.inc:151
                                                                     >=> '7'
                                                                   >=> 7

Array: array (0 => array (0 => '5'), 1 => '7', 2 => '7')
is translated via db_query() to invalid values 1, 7, 7 instead of 5, 7, 7

kenorb’s picture

Title: read-only nodereference using dropdown component is not passed on when submitting the form » disabled nodereference select component is not passed on when submitting the form
Status: Active » Needs review
StatusFileSize
new789 bytes

After patch, select are updating successfully (tested also on multi-select nodereferences).
Also in this patch there is another fix of some other bug, when values are copied from #default_value to #value they are not parsed via drupal_map_assoc() function in form_builder so they are in different format (array(0 => option1, 1=> option2, ...) instead of array(option1 => option1, option2 => option2, ...), so the first value will be always deleted

See nodereference_widget() function:

      case 'process form values':
...
          // drop the 'none' options if other items were also selected
          elseif (count($items['nids']) > 1) {
            unset($items['nids'][0]);
          }

it's resolved by adding additional empty key (array_unshift).

moshe weitzman’s picture

Status: Needs review » Closed (duplicate)

this is a general problem with disabled fields. see http://drupal.org/node/227966. please reopen if this problem is not a dupe of that one.

gcassie’s picture

I was able to work around this by setting the disabled field's value to it's default value in hook_form_alter.

      $form['field_example']['nids']['#disabled'] = true;
      $form['field_example']['nids']['#value'] = $form['field_example']['nids']['#default_value'][0];

It passes validation and doesn't wipe out the original value.

gcassie’s picture

To do the same thing for userreference fields:

    $form['field_example']['uids']['#disabled'] = TRUE;
    $form['field_example']['uids']['#value'] = $form['field_example']['uids']['#default_value'][0];