Tech Blog :: How to make a Views "exposed filter" dropdown appear as checkboxes
How to make a Views "exposed filter" dropdown appear as checkboxes
I'm using Views' "expose filters as a block" functionality in a custom search page. One of the filters is for content type, and users need to be able to select multiple options. Views can only generate multi-select lists as dropdowns, however, and the designs require checkboxes. Using a hook_form_alter to flip the #type from 'select' to 'checkboxes' fails because the form API structures those so differently. The views_filter_pack module claims to be able to convert from one to the other, but is extremely over-engineered for this purpose. Some searching around showed that other people had the same problem but no solutions seemed to work.
Then it dawned on me that I didn't need Drupal or Views to use checkboxes, I just needed the browser output to be rendered as checkboxes.
So I did a test in Firebug, rewriting the <select> as checkboxes, with the
same name and value's, and it worked!
With that revelation, I made a hybrid of theme_select() and theme_checkboxes() called theme_select_as_checkboxes(), which takes a select element but renders checkboxes. Here's the code:
/** * hack to make exposed dropdowns appear as checkboxes * (can't do it w/ form_alter b/c whole structure is different) * just render the options directly as checkboxes, pass the values the same as the SELECT, * tricks the form api and views to think it's a dropdown * [registered w/ hook_theme, toggled w/ #theme in form_alter] */ function theme_select_as_checkboxes($element) { $output = ''; $selected_options = (array) $element['#post'][$element['#name']]; // the selected keys from #options foreach($element['#options'] as $key=>$value) { $id = $element['#id'] . '-' . $key; // custom // is this option selected? $selected = (array_search($key, $selected_options) !== false); // (returns key or false) $checkbox = '<input type="checkbox" ' . 'name="'. $element['#name'] . '[]' .'" ' // brackets are key -- just like select . 'id="'. $id .'" ' . 'value="'. $key .'" ' . ($selected ? ' checked="checked" ' : ' ') . drupal_attributes($element['#attributes']) .' />'; $output .= '<label class="option" for="'. $id .'">' . $checkbox .' '. $value .'</label>' . "\n"; } return theme_form_element($element, $output); // wraps it neatly }
To enable it, register the function in hook_theme() with 'select_as_checkboxes' = array( 'function' => 'theme_select_as_checkboxes'), and set the field you want, in my case 'type', to use the custom theme function: $form['type']['#theme'] = 'select_as_checkboxes';
And it works!
I find this a lot more sensible than converting the whole tree structure in a form_alter. The rendering itself is basically Drupal-standard, it just happens to mix up the types a little.
Google: TheBuckSt0p
Facebook: BenBuckman
LinkedIn
Github: newleafdigital
@thebuckst0p
Delicious: thebuckst0p
Drupal.org: thebuckst0p
Hi Ben,
This looks like just the solution I'm looking for!
I haven't been using Drupal long. Please can you explain a little clearer how and where to "register the function in hook_theme()" and also to "...set the field you want...to use the custom theme function".
Thanks,
(another) Ben
(You didn't leave an email so I'm not sure if you'll see this response...)
In your custom module, create a
function MODULE_theme()(see the API doc), which returns an array containing [at least] one element, 'select_as_checkboxes', as described.You set the field in a
hook_form_alter, (checking for the$form_idor$form['#id']to control its scope), setting#themeas described.Let me know if that makes it any clearer.
Perfect solution!
Check out this module: http://drupal.org/project/better_exposed_filters
Post new comment
Don't bother putting in spam links. They'll be set to
rel=nofollowand will be removed and reported as spam shortly after submitting.