Making CCK fields read-only in Drupal 6

Posted on 2012-05-14 04:00:00+00:00

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

Ata2012-08-16 12:03:12+00:00

liked and effective. Its working. Thanks

Reply
Operations2012-10-05 18:41:44+00:00

Nice & Tricky -- I liked restoring the value !

Reply
Igor2013-06-12 17:33:00+00:00

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

Reply
Nick Lewis2013-07-01 11:25:00+00:00

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
silviogutierrez2013-07-03 01:52:56+00:00

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

Reply
Hélène2013-10-19 19:19:02+00:00

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
silviogutierrez2013-11-04 16:49:11+00:00

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
Neil2014-07-31 07:21:45+00:00

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
silviogutierrez2014-07-31 16:15:30+00:00

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

Post New Comment

We will not expose this.