I've tried to apply #disabled to serveral cck fields at this point, via weighted hook_form_alter() calls, but have yet to see any field respond.

Has anyone been able to successfully apply #disabled to a cck field?

Comments

yched’s picture

Applying to one of the CCK wrappers won't work, you need to apply it to the actual Form API element that supports #disabled (http://api.drupal.org/api/file/developer/topics/forms_api_reference.html...)
Meaning the '#type' => 'textfield', 'textarea', 'select'... element

Moonshine’s picture

Hi yched!

Thanks for the info... However, I think that is actually the key to the problem. Those '#type' => 'textfield', 'textarea', 'select'... elements aren't available via hook_form_alter(), as CCK hasn't built them out yet.

However, in the very next FAPI step (drupal_form_builder()), core processes #disabled elements via _form_builder_handle_input_element(). So there doesn't seem to be a place where #disabled can be inserted w/ CCK elements, unless I'm missing something obvious? #process, #after_build, #pre_render are all too late.

The only thing I've had success with is using a call like this, within one of those later steps, to mimic what core actually does with #disabled fields.

$elements['field_tester'][0]['value']['#attributes']['disabled'] = 'disabled';

Which is fine, but I'm still thinking that ultimately CCK may want to honor it itself if needed.

rsantiag’s picture

Hi Moonshine,

Where did you put that code?? I call it in hook_form_alter, but doesn´t work!!!

I can´t believe nobody needs this feature before!!!

yched’s picture

@Moonshine : hm, of course you're right, elements are not processed yet by the time form_alter runs...
That's a little annoying I guess, not only about #disabled.

Moonshine’s picture

@rsantiag - Code like that would have to be put in a step that comes after CCK has added the actual form elements. So you're looking at either #process, #after_build or #pre_render if you want to put in disabled code like that.

@yched - Yeah, it does make things a little awkward, as you really are religated to working with post build steps when working with CCK forms. But honestly 99% of the time it's not a big deal as you can still to what you want via those later steps. The only place where it's are real showstopper is when it's something that's dealt with in drupal_form_builder like #disabled. I'm not sure what else is really handled there off hand.

If it *was possible to build out the fields earlier, it would certainly clear up some confusion I see come up on IRC more and more. Most people just expect everything to be available in _form_alter. Not sure if that was a change from the D5 version or not.

karens’s picture

This is a difference in D6 -- the CCK fields now use FAPI and get built out in #process. The only thing that happens in form_alter() is to attach the top level, unprocessed, element to the form. This was done to allow widgets to handle their own pre- and post-processing, to make CCK's core multiple value handling easier, and to make it possible to 'nest' elements (like the nodereference field which then in turn builds out either an optionwidgets widget or a text widget).

The top level element is there during form_alter, so you can attach your own #after_build or #pre_render function to the top level of the field in form_alter(), and your custom function will be get the fully-processed form element that can be altered any way you like. I wouldn't use #process, you might still be too early at that point, depending on where and how you use it.

Since CCK widgets now use FAPI, you really need to know a little FAPI to work with them, but it's not really any harder than using form_alter.

Another alternative, if you only want to disable it, would be to do it in a custom theme or preprocess instead of in form_alter. That might be easier, and it might be a more logical place to do it.

rsantiag’s picture

Finally I got it working!!

The steps:

1. Add a new callback when the field is "#pre_reder"ing:

function mymodule_elements() {
return array(
'text_textarea' => array( // I need to disable a Text Area field type
'#pre_render' => array('mymodule_field_process'),
),
);
}

2. Treat the field when callback funtion will be called:

function mymodule_field_process($element) {

if ($element['#field_name'] == 'field_disabled' ){ // Change field_disabled with the real name of your field. You can add here any other conditions you want.
$element['value']['#attributes']['disabled'] = 'disabled';
}

return $element;
}

That's all folks!!

thanks for the help!!

greggles’s picture

The solution from #7 fixed this for me.

I'll admit that this is far beyond my realm of knowledge of FAPI and CCK, but it sure would be nice if we could just form_alter in a #disabled like we do for every other field type.

greggles’s picture

Status: Active » Fixed

Spoke a little too soon - if I try to submit fields that I've disabled in that manner I get a validation error:

"Fieldname field is required."

All the same, this seems "fixed" and/or a duplicate of #336355: Unable to add '#attributes' or use '#disabled' = true via hook_form_alter() where I found a similar answer.

markus_petrux’s picture

Try also setting ['#required'] = FALSE

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

danielb’s picture

Title: CCK elements support #disabled? » Correctly using hook_form_alter on CCK fields

I thought i'd change this since people search for this on google

greggles’s picture

Title: Correctly using hook_form_alter on CCK fields » Correctly using hook_form_alter on CCK fields for attributes like #disabled

Sure, great idea.

greggles’s picture

See also http://drupal.org/node/357328 in the handbook which documents how this can be achieved.

andreiashu’s picture

greggles: that handbook came just on time for me. It is just great when I can be reassured on some ideas.
Thanks !

d2f’s picture

I just found that someone can patch the script

see http://drupal.org/node/404974

but I still don't know how to implement the function

eikes’s picture

for me, this worked, i had to pay attention to the groups the fields were in:

<?php
function mymodule_form_alter(&$form, $form_state, $form_id) {
  $form['#after_build'][] = 'mymodule_after_build';
}

function mymodule_after_build($form, &$form_state) {
  // This is for a node reference field:
  $form['field_refref']['nid']['nid']['#value'] = $some_value;
  $form['field_refref']['nid']['nid']['#attributes']['disabled'] = true;
  // This is for an integer field:
  $form['group_something']['field_number'][0]['value']['#value'] += 1;
  return $form;
}
?>