How to split the exposed filters to separate blocks?

Comments

bigsyke’s picture

Sub

dude74’s picture

after 3 days to look for a solution, finally finding a simple issue. I use views 6.x.3, but should work with D7.

My goal was to display, on taxonomy term pages for a commercial website :
1 - an exposed form block with only sort at the top of the page
2- a different exposed block containing only term filters on the 1st left side region.

But In views, exposed filter in a block provides only one block, and related modules (better filter, views hacks,...) don't allow creation of separate blocks. Oh no ! my pretty website... Can't conceive mixing filter and sort criteria in a single block. Standars are sort at the top, and filters on the left !!! The only way with css is the absolute position for sort or filter id's, and that's impossible for my project.

NB : I use multiple vocabularies / terms on each node (color : red, white, ..., size : l, xl, ...).

I read issue for my problem suggesting to duplicate the view and play css with the 2 exposed blocks on the same page. Doesn't work for me (views 6.x.3), problem was the end-path on the "duplicate" exposed block returned "All" instead of the current term id (as in the "original" exposed block).

For my universal & simple issue, you need php filter module (and views !).
1 - override taxonomy_term - page - in views with your sort & filter exposed filters, form in a block
2- create a node type called phpinput. Let all standard option
3 - create a new content of phpinput type. Title "phpinput".
4- in the body of the new content :
D6 (tested & working fine)

   if ($block = module_invoke('views', 'block', 'view', '-exp-taxonomy_your_exposed_block_id') ) {
    print $block['content'] ;
  }

D7 (no tested)

   if ($block = module_invoke('module_name', 'block_view', 'block_delta') ) {
  print render($block);
  }

see http://drupal.org/node/26502
It creates a new clone block of your exposed filter&sort block, working perfectly.

5- save your new content and look at the node id (hover the node edit button...)
6- Add a new view (node), create a block display called exposedfiltercopy. Add node-body field and a hidden filter : node-id = "id_of_the_new_phpinput_content_you_remember_if_you_follow_the_steps_above" - save the view
7 - administer the blocks and place the "original" exposed block in the content top region, and the "clone" block (exposedfiltercopy) on the 1st side left. Actually, you put the 2 blocks in the regions you want, depending of your website design...
8 - configure the blocks visibility (block configuration)
9 - use css display : none to hide filters on the top block and sort on the left

And you gat it baby !!!! That works perfectly for me, after 3 days to play with views-exposed-form.tpl.php, hook_form_alter, views cloning ot the taxonomy_term-page aso...

Bonus Taxonomy : use views hacks to display only term filters related to the current content displayed on the page. Module taxonomy filter is fine too, but don't work on my parent term pages (I have a 4 levels terms hierarchy)

I'm not a drupal expert, and "read but don't talk" php. So if you have technical questions, i'm quite sure i could not answer (and i'm french with a low english level).

deggertsen’s picture

Here are some related issues I have found:

#1420332: How to separate exposed filters and sort?
#1444758: Separate exposed sort form from exposed filter block

I personally still do not have a working solution. I like the solution listed above, but the instructions are a little unclear. Would it be possible to create a custom block using a php filter and call the exposted block? Any help would be great.

aa2007’s picture

In my case, I gave up the exposed filters in favor of the Search API + Facet API

deggertsen’s picture

Using Drupal Commerce I have a product display view with relationships to a product which refers to a class node which refers to a presenter node (product display -> product entity -> class node type -> presenter node type). I have filters that are based on the presenter node type, making it 4 relationships deep. I had major issues getting this to work with Search API and Facets.

oeroek’s picture

I used option #2 for Drupal 7 and adjusted it a little bit.

1) I enable php filter. it's a core module. Make sure you limit access to this filter to heavy super admin only.
2) I make a custom block in the region content so it shows above my views page.
3) I make a views page with filter+ sort options+auto submit and expose them in a block. These are options in views.
4) I put the exposed block in my sidebar: for the filter options. I minimize the sort options by making them collapsible. Again, these are options in views.
5) in my custom block I enable the filter+sort options by using the following code:

<?php
$block = module_invoke('views', 'block_view','-exp-arrangement-page');
print render($block['content']);
?>

You have to replace '-exp-arrangement-page' with the name of your exposed block. You can find the name if you go to your block page and configure the exposed form block. In the url, just before '/configure' you can find the name of the block.
6) you could hide the filter options with css.

I did not hide the filter options with css since this would add a lot of duplicate html. In the custom block, I added some code to replace the #markup with my own.

7) if you have devel you can include dpm($block); in your custom block. You will find the markup at $block['content']['#markup']. I copied the markup and stripped the html for the filter options. I made the new markup available with the following code:

$block['content']['#markup'] = '<form class="ctools-auto-submit-full-form" action="/arrangement" method="get" id="views-exposed-form-arrangement-page" accept-charset="UTF-8">
  <div>
    <div class="views-exposed-form">
.............

8) The html changes based on the options people choose. I have two options:

<option selected='selected' value="field_prijs_arrangement_value ASC">Option 1</option>
<option value="field_prijs_arrangement_value DESC">Option 2</option>

Option 1 is selected. I use some php to change which option is selected based on the query in the URL. The code looks like this. Since I lack skills in PHP I am sure the code can be shorter. But for now this works for me.

<?php
$block = module_invoke('views', 'block_view','-exp-arrangement-page');
$q1 = 'selected="selected" ' ;
 $q2 ='';
$q = drupal_get_query_parameters();

if(isset($q['sort_bef_combine'])){
if(strpos($q['sort_bef_combine'],'DESC') !==false) {
 $q2 = 'selected="selected" ' ;
 $q1 ='';
}}

$block['content']['#markup'] = '<form class="ctools-auto-submit-full-form" action="/arrangement" method="get" id="views-exposed-form-arrangement-page" accept-charset="UTF-8">
  <div>
    <div class="views-exposed-form">
		<div class="views-exposed-widgets clearfix">
          <div class="views-exposed-widget views-submit-button">
			<div class="form-item form-type-select form-item-sort-bef-combine">
				<select id="edit-sort-bef-combine" name="sort_bef_combine" class="form-select">
<option value="field_prijs_arrangement_value ASC"'.$q1.'>Option 1</option>
<option value="field_prijs_arrangement_value DESC"'.$q2.'>Option 2</option></select>
			</div>
			<input class="ctools-use-ajax ctools-auto-submit-click js-hide form-submit" type="submit" id="edit-submit-arrangement" name="" value="Zoeken" />    </div>
          
		</div>
	</div>
  </div>
</form>';

print render($block['content']);
?>

NB: offcourse the markup part of the code will be different in every implementation, depending on the options you use in views.

deggertsen’s picture

@oeroek Awesome! Finally a decent solution with solid instructions. I did not follow set 7 and 8 though because I am using far too many filters to try and change the selected value for each one of them... Because of this, using AJAX does not work unfortunately as both blocks don't sync up when there is no page reload.

Still hoping for a solution to be built into views though. Seeing as this solution works of building two separate filter forms manually, it would seem that it could be done using the views UI if you simply allowed multiple exposed forms with the ability to assign different filters to each form (maybe use filter groups?). Then you could determine for each exposed form whether it would be exposed in a block or not with separate settings for each. There's my dream...

Exploratus’s picture

Interesting solution #6, bt I agrea with #7. I really think the sort filter is the achilles heel of views exposed filters. Very counter intuitive and not in line with traditional sort filter solutions found on any major site (be it CMS or Eccomerce). Sort is a different function than filter, yet drupal just lumps it into one block, which is not what the typical person expects or is used to. I find the sort so counter intuitive that I rather not offer it on my sites than show some weird layout that nobody is going to understand.

berliner’s picture

I hacked a possible solution into a module: https://drupal.org/sandbox/berliner/2087181
It comes as a views plugin. Once enabled there will be a new option in the views UI under "Exposed Form": Exposed form blocks. There you can enable an additional block. Enable the additional block, then on each filters configuration dialog you can choose where the exposed filter should show up. Additionally you can select "items per page" and sort options to be put into the additional block too.

The code is experimental, but it seems to work in two of my current projects. Note that it is still a hack. The solution is based on copying the default exposed form, hide selected elements there, create a copy of the exposed form with different form ids and place that in a block. On submission the form values will be rewritten to match the original filter keys.

Give it a try and give me feedback.

pinkonomy’s picture

@berliner:
Thanks for this module but I am not sure if this my case:
I just want to have two exposed filters on the same view,so as to put each one on separate pages ,but each will query the same view.
Is this possible with this module?
thanks

berliner’s picture

@pinkonomy: An easier solution for you would be to hide the filters that you don't want on individual pages using CSS.
I think you could also use my module, but as it is experimental code it would probably be safer to go for a CSS based solution. My module is dedicated to enable two filter blocks on the same page.

lucsan’s picture

Issue summary: View changes

I believe you can make the original technique easier by using a block instead of a node and content type.

Put the render($block['content']) code into a user created block (you still need php format), and place the block where ever you want.

You still need to hide the unwanted form items with CSS.

You can also use _block_load_blocks(); to find the block delta on the page to use in module_invoke(); .