1

I have a CCK field (text, options widget, predefined value list) I'm using on two Node Types. On one Node Type, I'd like to allow an unlimited number of selections. On the other Node Type, I'd like to restrict the user to a single selection.

Currently, I've configured the CCK field to allow unlimited values, and am using this hook_form_alter() code:

/*
 * Implementation of hook_form_FORM_ID_alter().
 */
function custom_form_custom_node_form_alter(&$form, &$form_state) {
  // http://drupal.org/node/726282
  $form['#after_build'][] = 'custom_after_build';
}
function custom_after_build($form, &$form_state) {
  $form['field_custom' ]['value']['#multiple'] = false;
  return $form;
}

So far, so good: the field shows up as single-value on one Node Type, and multi-value on the other.

But when I click Save, the data doesn't end up in the node — I presume this is because the single-value and multi-value fields store data differently, and CCK's submit handler is expecting the data in a different format.

What do I need to do to get the single-value field data into a format CCK will understand for a multi-value field?

So far I've tried:

  • implementing a #validate handler to alter the $form_state array to match the $form_state array produced by submitting a multi-value field — no effect
  • implementing hook_nodeapi() $op==='validate' to alter the field values in the $node object — no effect

2 Answers 2

1

You need to implement the hook_nodeapi and use the operation "presave"

Presave will have all the data submitted from the form and you can then alter it here just before it goes into the database.

If you have the devel module do a dpm($node); to see what data you are getting.

the important thing is that the field for multi values will be expecting an array so it may be as simple as grabbing the data from the form and adjusting it to pass it as an array.

EDIT

Aah ok validation....

I would probably turn off validation for that item by using the: '#element_validate' property, this way you can target validation for that specific element see the fapi docs on drupal. http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/6#element_validate

2
  • The form isn't getting as far as the presave nodeapi op — it gets hung up during the validation phase, since this now-single-value field doesn't think it has valid data.
    – smokris
    Commented Feb 27, 2012 at 23:43
  • Regarding the edit: Thanks, @Andre — that sounds like a far less invasive option than the answer I proposed.
    – smokris
    Commented Feb 29, 2012 at 19:10
0

A working, but ugly, solution — manually remove the form validation errors:

/*
 * Implementation of hook_form_FORM_ID_alter().
 */
function custom_form_custom_node_form_alter(&$form, &$form_state) {
  // http://drupal.org/node/726282
  $form['#after_build'][] = 'custom_after_build';
  $form['#validate'][] = 'custom_validate';
}
function custom_after_build($form, &$form_state) {
  $form['field_custom' ]['value']['#multiple'] = false;
  return $form;
}
function custom_validate($form, &$form_state) {
  // since we're now rendering a single-value-field, we need to move the data back into the multivalue-field format CCK expects
  $selectedValue = $form['field_custom']['#value']['value'];
  $form_state['values']['field_custom'][0]['value'] = $selectedValue;

  // clear related form errors set by other validation handlers
  $errors = form_get_errors();
  form_set_error(NULL, '', TRUE);
  foreach ($errors as $k => $v) {
    if ($k !== 'field_custom][value') {
      form_set_error($k, $v);
    }
  }

  // clear related messages set by other validation handlers
  $errors = drupal_get_messages('error');
  foreach($errors['error'] as $error) {
    if ($error !== 'Custom field is required.') {
      drupal_set_message($error, 'error');
    }
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.