Sunday, March 15, 2009

How to set the disabled attribute of a CCK field

Code snippet: How to set the disabled attribute of a CCK field
Drupal 6.x · No known problemsLast modified: January 11, 2009 - 18:41
Here's a code snippet that you can use to set the disabled attribute of a CCK field.

First, you need to create a small module containing the following code:


<?php
/**
* @file
* Custom module to set the disabled attribute of CCK fields.
*/

/**
* Implementation of hook_form_alter().
*/
function mysnippet_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node'])) {
// Use this check to match node edit form for a particular content type.
if ('mytype_node_form' == $form_id) {
$form['#after_build'][] = '_mysnippet_after_build';
}
// Use this check to match node edit form for any content type.
// if ($form['type']['#value'] .'_node_form' == $form_id) {
// $form['#after_build'][] = '_mysnippet_after_build';
// }
}
}

/**
* Custom after_build callback handler.
*/
function _mysnippet_after_build($form, &$form_state) {
// Use this one if the field is placed on top of the form.
_mysnippet_fix_disabled($form['field_myfield']);
// Use this one if the field is placed inside a fieldgroup.
// _mysnippet_fix_disabled($form['group_mygroup']['field_myfield']);
return $form;
}

/**
* Recursively set the disabled attribute of a CCK field
* and all its dependent FAPI elements.
*/
function _mysnippet_fix_disabled(&$elements) {
foreach (element_children($elements) as $key) {
if (isset($elements[$key]) && $elements[$key]) {

// Recurse through all children elements.
_mysnippet_fix_disabled($elements[$key]);
}
}

if (!isset($elements['#attributes'])) {
$elements['#attributes'] = array();
}
$elements['#attributes']['disabled'] = 'disabled';
}
?>


Explanation:

Setting the #disabled attribute of the element in form_alter doesn't work because the FAPI process handler of the CCK field won't transfer the #disabled attribute to its children elements. So we need to find a different method...

We can do this using our own #after_build handler, but here we cannot simple set the $element['#disabled'] attribute of the element. The reason is this attribute is transformed into $element['#attributes']['disabled'] by _form_builder_handle_input_element executes(), which is the format FAPI theme functions know about. However, _form_builder_handle_input_element executes() is executed before #after_build handlers are invoked, so our own handler needs to set the value as the theme functions expect. See form_builder().

Finally, we need to use a recursive function so that we can set the disabled attribute of all the FAPI elements that depend on the CCK field we're interested in. Think for example about a checkboxes element, etc.

No comments: