Making CCK fields read-only in Drupal 6

Posted on May 14, 2012

Generally, using form alter on any form field and setting #disabled => TRUE works great. However, form alter is too early of a hook to use on CCK's fields. Moreover, if you disable a field, the browser won't even post the value. This can result in annoying validation issues. So why this post? I found that the most popular post on this topic did not work for me. This post applies to Drupal 6. But relax, there's a Drupal 7 technique.

The correct and safe way to do lock changes to a widget is to mark its HTML elements as read only, not as disabled. To do this, we use the readonly attribute. This ensures that the browser posts the value, unlike disabled. But we can't just stop here. We need to make sure the value isn't changed by a crafty user modifying his post request.

Learning Drupal? Subscribe to my Drupal articles, tips and tutorials.

First, let's hook in to the node form so we can add our #after_build callback. Keep in mind that in this example, we're adding our callback to all node forms. You might want to further limit this to a specific content type.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php

/**                                                                           
 * Implements hook_form_alter().                                              
 */                                                                           
function example_form_alter(&$form, &$form_state, $form_id) {                 
  if (isset($form['#node']) && $form_id == $form['#node']->type .'_node_form') {
    $form['#after_build'][] = 'example_after_build';                          
  }                                                                           
}

Let's keep things simple and modify a text widget. For simple widgets, CCK generally uses the key value.

1
2
3
4
5
6
7
8
<?php

function example_after_build($form, &$form_state) {                           
  $field = 'field_example_cck_field';                                         
  $form[$field][0]['value']['#attributes']['readonly'] = 'readonly';          
  $form_state['values'][$field][0]['value'] = $form[$field]['#default_value']['value'];
  return $form;                                                               
}

And that's it! You can now count on your field being readonly. Yet it will still be posted by the browser. And even if a user tries to post a changed value - or uses Firebug to edit the contents of the fields - our build function restores the original value.

Below is the complete code for reference.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

/**                                                                           
 * Implements hook_form_alter().                                              
 */                                                                           
function example_form_alter(&$form, &$form_state, $form_id) {                 
  if (isset($form['#node']) && $form_id == $form['#node']->type .'_node_form') {
    $form['#after_build'][] = 'example_after_build';                          
  }                                                                           
}

function example_after_build($form, &$form_state) {                           
  $field = 'field_example_cck_field';                                         
  $form[$field][0]['value']['#attributes']['readonly'] = 'readonly';          
  $form_state['values'][$field][0]['value'] = $form[$field]['#default_value']['value'];
  return $form;                                                               
}

Comments

AtaAug. 16, 2012, 12:03 p.m.

liked and effective. Its working. Thanks

Reply
OperationsOct. 5, 2012, 6:41 p.m.

Nice & Tricky -- I liked restoring the value !

Reply
IgorJune 12, 2013, 5:33 p.m.

Thanks a lot - google'd it for a while, couldn't find anything. This solved the issue.

Reply
Nick LewisJuly 1, 2013, 11:25 a.m.

This works beautifully for text fields! How about a single Checkbox though? I am guessing that the key "value" doesn't apply to checkboxes?

Reply
silviogutierrezJuly 3, 2013, 1:52 a.m.

Did you try it? it should work. If I recall correctly, individual checkboxes are also stored with a 'value' key.

Reply
HélèneOct. 19, 2013, 7:19 p.m.

I need the field to be open for input at the create node stage but readonly whenever it is open for edit at a later time. Can the form_alter hook be used for when the node is in edit mode?

Reply
silviogutierrezNov. 4, 2013, 4:49 p.m.

It sure can. Just check that $form['#node'] has an nid. If it does, that means you're editing instead of creating. Hope that helps.

Reply
NeilJuly 31, 2014, 7:21 a.m.

I think a easy way.

$form['field_sw_part']['#pre_render'] = array('field_sw_part_readonly');

function field_sw_part_readonly($element) { $element[0]['value']['#attributes'] = array('readonly' => 'readonly', 'class' => 'readonly'); return $element; }

Reply
silviogutierrezJuly 31, 2014, 4:15 p.m.

Neil,

This will not prevent a user from manually editing the POST data and changing the value. It will only make the field readonly in the browser. So data integrity is not guaranteed.

- Silvio

Reply
Bad CreditOct. 17, 2018, 2:57 a.m.

poor credit loans guaranteed approval installment loans online texas bad credit loans direct lenders credit loans guaranteed approval

Reply

Post New Comment