Drupal 7 Read-Only Fields on Forms

Aug
2014
11
Let's say you want to have a form that the field is disabled, can take-update its value through a jquery-ui element but you do not want the user to be able to change the value of the field. For example you have a timer field where you have quarters of an hour and you want to let the user choose from a jquery-ui element that looks like a clock e.g 45 min or 30 min or 15 min each time the user chooses a value the extra field will be updated and will be readonly. There is a small catch here. Using the DRUPAL FORM API table reference we can see that we have the #disabled option. This is fine but it does not update. Yup! and this is why it is called "disabled" actually (https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.h...) :) so what else options do we have then? "Readonly"! to the rescue. Besides this is better in UX and much safer than a disabled field. 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 or her post request. In order to make this work you need a tiny custom module to override the form field settings. We need to know the name of our field e.g field_that_needs_readonly_attr or something better! so in our custom_module.module file we add the hook_form_alter function
<?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'][] = 'make_readonly_after_build';                         
  }                                                                          
}
?>
and then the "make_readonly_after_build" function
<?php
function make_readonly_after_build($form, &$form_state) {                          
 
$field = 'field_that_needs_readonly_attr';
 
$form[$field]['und'][0]['value']['#attributes']['readonly'] = 'readonly';
 
$form_state['values'][$field]['und'][0]['value'] = $form[$field]['und'][0]['value']['#default_value'];
  return
$form;
}

?>
And that's it! You have a readonly field now and you can out and grab a beer. Problem solved!
Cats: 
this is an arrow pointing back to the top of the page