Quick and dirty views exposed filter form select replacement in a block
I have a client who wants an exposed filter but, instead of having a select drop down, would like to replace it with a set of links.
This is not an uncommon use case, and there are some existing examples on how to do this. It's pretty easy, since views will read a value for the exposed filter from a query string.
But what if your exposed filter form is in a block? Exposed filter forms in blocks only work if you enable AJAX for the exposed filter, and the ajax dynamically replaces the contents of the block with the results of your selection.
In this case, in addition to replacing the select with links, you need to add a javascript event handler to the links that will duplicate (or invoke) the ajax.
Step 1. my_theme_preprocess_views_exposed_form
You could also use hook_form_alter, for some reason this seemed more straightforward to me.
We're going to go through the select key/value pairs, and create a set of links that we add to the $variables array. We're also going to include a javascript file that will be created in step 2.
<br>function my_theme_preprocess_views_exposed_form(&$variables) {<br> // return an array of links that we can display in the form<br> $filter_links = array();<br> foreach ($variables['form']['tid']['#options'] as $key => $value) {<br> $filter_links[] = l($value, '', array(<br> 'attributes' => array(<br> 'class' => 'filter-link',<br> 'data-value' => $key,<br> ),<br> 'fragment' => 'filter',<br> ));<br> }<br> $variables['filter_links'] = $filter_links;<br>
<br> drupal_add_js(drupal_get_path('theme', 'my_theme') . '/js/exposed_filter.js', 'theme');<br>}<br>
Step 2. exposed-filter.js
Add js/exposed-filter.js to your theme.
We're going to add a click event handler to each of the links we created in step 1 that will set the value of the existing submit input, and will submit the form. Once the form is submitted, the jQuery behavior supplied by Views takes over.
<br>Drupal.behaviors.my_theme_exposed_filter = function(context) {<br> $('a.filter-link', context).bind('click', function() {<br> $('select#edit-tid').val($(this).attr('data-value'));<br> $('div.view-filters form').submit();<br> });<br>}<br>
Step 3. views-exposed-form--VIEW-NAME--block-DELTA.tpl.php
Copy views/themes/views-exposed.form.tpl.php to your theme so that you can print the links you added in the preprocess function.
<br><div class="links"><br> <?php<br> foreach ($filter_links as $link) {<br> print "$link\n";<br> }<br> ?><br></div><br>
Optionally, you can remove the submit button here if you want.
Step 4. Hide the select input in CSS
There's more than one way to do this. However, it's required that you hide the select instead of omitting it, since Views will read from the select when the form is submitted.
<br>form#views-exposed-form-VIEW-NAME-block-DELTA div.views-widget {<br> display: none;<br>}<br>
This is, admittedly, an ugly way to do it, but it works. An extension to the better exposed filters project would be much nicer.
Also, *why* is it that exposed filters only work in blocks via ajax? Shouldn't it be possible to reload the page that a block is on with a query string that the block view can recognize? You could use the block ID to disambiguate in the case that multiple blocks with exposed filter forms were on the same page...