I have built a custom CCK field type that stores 2 columns. hook_widget() returns an $element with 2 form elements, the 2nd of which is blank until the value of the first element is chosen. I cannot figure out how to add the data into the 2nd element via #ahah and have the form rebuilt so that I don't receive validation errors (because the #options for element #2 didn't exist when the widget was initially built). Can this be achieved in a CCK widget? I know I've seen this elsewhere, i.e. hierarchical select in D6 or addressfield module in D7 (this current task is D6 unfortunately).
My widget and #ahah callback is currently:
<?php
/**
* Implementation of hook_widget().
*/
function custom_cck_product_upgrades_widget(&$form, &$form_state, $field, $items, $delta = 0) {
// Generate a unique ID for this product upgrades wrapper.
$product_upgrades_wrapper_id = implode('_', array($field['field_name'], $delta));
$element['#type'] = 'fieldset';
$element['#title'] = 'Product Upgrades';
$element['#collapsible'] = TRUE;
$element['product'] = array(
'#title' => 'Product',
'#type' => 'select',
'#options' => array('- Select -') + _custom_cck_product_upgrades_get_products(),
'#default_value' => isset($items[$delta]['product']) ? $items[$delta]['product'] : NULL,
'#ahah' => array(
'path' => 'custom-cck-product-upgrades/ajax/product-upgrades',
'wrapper' => $product_upgrades_wrapper_id,
'method' => 'replace',
'effect' => 'fade',
),
);
$element['value'] = array(
'#title' => 'Product Upgrades',
'#type' => 'checkboxes',
'#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
'#prefix' => "<div id='{$product_upgrades_wrapper_id}'>",
'#suffix' => "</div>",
);
// Get all upgrade options for the current product.
if (isset($items[$delta]['product'])) {
$options = array();
$result = db_query("SELECT * FROM {custom_products} WHERE product_family = %d", $items[$delta]['product']);
while ($row = db_fetch_array($result)) {
$options[$row['id']] = $row['name'];
}
$element['value']['#options'] = $options;
}
return $element;
}
function custom_cck_product_upgrades_widget_ahah($form, $form_state) {
// Load the form from the cache.
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
$form['#programmed'] = $form['#redirect'] = FALSE;
$form = form_builder($form['form_id']['#value'], $form, $form_state);
$form_state['values'] = $form['#post'] = $_POST;
form_set_cache($form_build_id, $form, $form_state);
// I can rebuild the element here, but it makes no difference because the original form doesn't know about this...
$element = array();
$output = theme('status_messages') . drupal_render($element);
return drupal_json(array('status' => TRUE, 'data' => $output));
}
?>