Found the answer to my issue in #1764350-6: Form rebuild overwrites selected values but it really wasn't related enough to post on that thread.
I've built a custom form using and my _submit contains:
$form_state['rebuild'] = TRUE; // needed to pass $form_state back to _form function
When I submit, all the other fields preserve their inputed values (which is what I want because they are filters for table, so people want to keep what they've filtered by). But the HS field was losing it's value. It came through in $form_state['values'] but for some reason #default_value wasn't being respected.
Tracked it down to this chunk of code in the hierarchical_select.module:
function form_hierarchical_select_process($element, &$form_state, $complete_form) {
...
// This prevents values from in $form_state['input'] to be used instead of
// the generated default values (#default_value).
// For example: $element['hierarchical_select']['selects']['0']['#default_value']
// is set to 'label_0' after an "Add" operation. When $form_state['input']
// is NOT erased, the corresponding value in $form_state['input'] will be
// used instead of the default value that was set. This would result in
// undesired behavior.
drupal_array_set_nested_value($form_state['input'], $element['#array_parents'], array());
...
}
That would do it!
So I used the other issue to add two #process callbacks to my HS form element:
$form['my_hs'] = array(
'#type' => 'hierarchical_select',
'#title' => t('My HS'),
'#size' => 1,
'#config' => array(
'module' => 'hs_taxonomy',
...
),
'#process' => array(
// Add our process function before the original process function
// so we can preserve the form_state[input] before HS deletes it
'MODULE_preserve_hierarchicalselect_input',
'form_hierarchical_select_process',
'MODULE_restore_hierarchicalselect_input',
),
);
Then those functions are pretty dead-simple, just working around by saving and restoring:
/**
* Hierarchical select form element type #process callbacks
*
* These are needed because HS overwrites the #default_value so we have to wrap
* it's processing to preserve, then restore, otherwise the value isn't kept
* when the form reloads.
*
* See line 808 in hierarchical_select.module for what we're working to avoid.
*/
function MODULE_preserve_hierarchicalselect_input($element, &$form_state, $complete_form) {
$element['#preserve_input'] = $form_state['input']['my_hs'];
return $element;
}
function MODULE_restore_hierarchicalselect_input($element, &$form_state, $complete_form) {
drupal_array_set_nested_value($form_state['input'], $element['#array_parents'], $element['#preserve_input']);
return $element;
}
Comments
Comment #1
spcalpo commentedI've tried this solution and (with some tweaking for my use case; I was crazy enough to want an 'add more' ajax functionality with hierarchical_select) seems like it's working as desired. Thank you for sharing, covenantd. :)
I have made a lot of use of hierarchical_select in recent projects. Makes me wish I had more time to help maintain it, as it is a very useful module with some quirks that have set me back for days here and there.