I've run into an issue with having multiple exposed filters on the same page, when a view is manually embedded multiple times (or just to test I tried also with Panels to load the view multiple times). To communicate the issue as easily as possible I made a short video clip (3.5mb):
http://www.davidnewkerk.com/files/video/views-exposed-filters.mov

I have a single view which I'm embedding multiple times in a node template using views_get_view(). The view has an AJAX exposed filter for Taxonomy: Term. My actual use case is more complex (each view instance gets unique content depending on a node reference argument), though to keep my testing and example as simple as possible, I've created 2 basic CCK types ("Test parent" and "Test") and a basic Taxonomy (terms: A, B, and C). I made several Test nodes and assigned terms to them.

Here's the code I'm using to embed the views in node-test_parent.tpl.php (the view has both a page and block display which I've tried, both giving the same issue):

  <h2>Embedded view copy 1</h2>
  <?php   
    $view = views_get_view('test');
    $view->set_display('page_1');
    $view->override_path = $_GET['q'];
    $viewsoutput = $view->preview();
    print $viewsoutput;
  ?>
  
  <h2>Embedded view copy 2</h2>
  <?php   
    $view = views_get_view('test');
    $view->set_display('page_1');
    $view->override_path = $_GET['q'];
    $viewsoutput = $view->preview();
    print $viewsoutput;
  ?>

While searching the Views issue queue I came across suggestions to use $view->override_path = $_GET['q']; to resolve what appears to be similar situations people have had, though it didn't seem to do the trick in my case. I've tried also assigning it other paths manually without luck. The same view is used multiple times since in my actual use case, it loops through an array of node references and outputs a copy for each.

The first embedded view's exposed filter works as expected. When clicking Apply for the second embedded view's filter, the instead of updating the results via AJAX, the page forwards to node/149?tid=14). Subsequently applying different values for the second view's filter updates the output of both views simultaneously.

Is there any way to get the exposed filters in this setup to work correctly? Is there perhaps a better approach to what I'm trying to do?

Thanks very much for your help! :)

Comments

merlinofchaos’s picture

Does it work better if you do $view->destroy() after you're done with it, and before you load it again?

dnewkerk’s picture

Hi Earl, thanks for the response :) I added $view->destroy(); to the PHP after printing each view (and even tried adding it before the second one's code for good measure too haha) but unfortunately no, no luck. I spoke briefly in IRC with cwgordon7 about it, and he said he believed it could be a bug in views. If so and development funding is needed to get it fixed, please let me know, as my client is open to paying for the fix (if you don't have time but could recommend a Views-savvy developer to work on a patch with, that'd be cool too).

Thanks!

dawehner’s picture

To summarize the problem:

This behavior is clear that it cannot be fixed without changing the identifier for non-ajax-views.

So ajax views:

Views uses this identifier to bind the submit event:

      $('form#views-exposed-form-' + settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-'))

As you see if you have multiple views with the same display and viewname you don't have a unique id anymore.
Jquery does only select the first id

So what would be possible here:

* Add the dom_id here(either class or id). Therefore the dom_id generation would have to be earlier then on the preprocess_views_view function
* Add the same class and use the class as identifier (that's this patch)
* This patch fails, because the response callback cannot set the html right.

So as conclusion, the problem is not that easy:

* We need the dom_id already on views_exposed_form level.
* The dom_id has to be used for exposed_form caching
* The dom_id has to be used for ajax commands

Perhaps i just overlook something, but it seams to be not that easy.

As alternative it would be possible to dynamically build up 50 different displays dynamically. It's not really hard with hook_views_pre_view.

dnewkerk’s picture

Hi dereine -

Would you be interested in fixing this Views issue as a paid project? If so, please send me a message with your rate and an estimate of how many hours you expect the fix may take so I can check with my client about the budget. If you don't have time to accept this project, please let me know as soon as possible (if that's the case would you refer me to another Views developer who you believe has the skills to write a quality patch for this issue that we can contribute back to Views module?).

Thanks, hope to hear from you :)

- David

mstrelan’s picture

I have the exact same problem. Subscribing

mstrelan’s picture

@dereine - When you say it's not hard with hook_views_pre_view() can you give me a hint as to how you would do this? This is what I've tried but it didn't work.

<?php
function MYMODULE_views_pre_view(&$view, &$display_id, &$args) {
  static $i;
  if ($view->vid == 4) {
    $view->display['default_'. ++$i] = $view->display['default'];
    $view->current_display = 'default_'. $i;
  }
}
?>
johnpitcairn’s picture

subscribe

mstrelan’s picture

OK I've worked out how to build up the dynamic displays and will post my solution for those who are interested. Would love to get this fixed in Views still.

Step 1: Embed your view

<?php
function MYMODULE_nodeapi(&$node, $op, $a3, $a4) {
  if ($op == 'view' && $node->type == 'MYNODETYPE') {
    $view = views_get_view('MYVIEW', TRUE);
    $view->set_display('default');
    if ($view->access('default')) {
      $args = implode('+', array('MYARG1', 'MYARG2'));
      $result = $view->preview('default', $args);
      if (!empty($result)) {
        $node->content['body']['#value'] .= $result;
      }
    }
  }
}
?>

Step 2: Add a dynamic display.
This needs to be based on some other part of the view. I have chosen args because this is the only difference between the different times I embed the view. You can not simply use an incremented integer, as the ajax handler needs to be able to repeat the same process.

<?php
function MYMODULE_views_pre_build(&$view) {
  if ($view->vid == MY_VIEW_ID && !empty($view->args)) {
    $edit_args = array();
    foreach ($view->args as $arg) {
      $edit_args[] = str_replace(array('+',','), '-', $arg);
      break; // In this case we only want the first lot of args otherwise ajax.inc adds in the default values for arg 2.
    }
    $new_id = implode('_', $edit_args);
    unset($view->current_display);
    $view->display['default_'. $new_id] = clone $view->display['default'];
    $view->display['default_'. $new_id]->id = 'default_'. $new_id;
    $view->display['default_'. $new_id]->handler->options['filters']['keys']['id'] .= '_'. $new_id;
    $view->set_display('default_'. $new_id);
  }
}
?>

Step 3: Alter the AJAX menu callback (or optionally hack views/includes/ajax.inc in step 4)

<?php
function MYMODULE_menu_alter(&$items) {
  $items['views/ajax']['page callback'] = 'MYMODULE_views_ajax';
  $items['views/ajax']['file'] = 'MYMODULE_views_ajax.inc';
  $items['views/ajax']['file path'] = drupal_get_path('module', 'MYMODULE');
}
?>

Step 4: Provide a new AJAX callback function in MYMODULE_views_ajax.inc (or hack views/includes/ajax.inc)

<?php
function MYMODULE_views_ajax() {
  module_load_include('inc', 'views', 'includes/ajax'); // ADD THIS LINE!!!

/*** Some text removed ***/

    // Load the view.
    if ($view = views_get_view($name)) {
      if (strpos($display_id, 'default_') === 0) {
        $display_id = 'default';
      }
      if ($view->access($display_id)) {

/*** Some text removed ***/

      }
    }
    $messages = theme('status_messages');
    $object->messages = $messages ? '<div class="views-messages">' . $messages . '</div>' : '';

    views_ajax_render($object);
  }
}
?>

And there you have it

cangeceiro’s picture

i'm also having this same issue with views 3-dev...subscribing.

mmilano’s picture

same issue:

$view1 = views_get_view('articles');
$news1 = $view1->execute_display('block_2', array('News Term 1'));

$view2 = views_get_view('articles');
$news2 = $view2->execute_display('block_2', array('News Term 2'));

$news2 will return the same as $news1 with the content of term "News Term 1"

if i reverse the order of the arguments, "News Term 2" content will display in both views.

$view1->destroy() did not work.

Next I tried creating 2 displays with the terms set as a filter instead of arguments. Each display has its own term. I get the same result.

$view1 = views_get_view('articles');
$news1 = $view1->execute_display('block_2'); // has a term filter set to news item 1

$view2 = views_get_view('articles');
$news2 = $view2->execute_display('block_3'); // has a term filter set to news item 2

I realize I probably shouldn't have to do views_get_view() again, but I was just trying new things.

Letharion’s picture

Category: support » feature

Obviously this can be done, but requires a bit of extra work.
I'm making this a feature request.

@merlinofchaos
Useful feature, or rare edge case?

iamjon’s picture

Assigned: Unassigned » merlinofchaos

Assigning to merlinofchaos for review

mayerwin’s picture

Subscribed

herveh’s picture

Any progress on this issue?
I encountered a different problem but that seems related by embedding 2 different views on the same page,
with taxonomy arguments from different vocabularies for each view.
I can't get both working at the same time, if I give my node taxonomy terms to both vocabularies targeted in the views, both views stop working...
But both views work separately if the second one is not on the page
Any idea?

mstrelan’s picture

@herveh - sounds like a different issue, you probably need to open a new support request. How are the arguments getting their values? If you are talking about exposed filters rather than arguments then you probably need to make sure you create a unique query string key for each view. This can be done in the same interface you use to expose a filter.

seanb’s picture

This issue seems to be fixed in the latest dev for 7.x.

waqarit’s picture

Not fixde, I have same issue :(

interestingaftermath’s picture

Unfortunately this is not fixed in the latest `dev`.

chris matthews’s picture

Status: Active » Closed (outdated)

The Drupal 6 branch is no longer supported, please check with the D6LTS project if you need further support. For more information as to why this issue was closed, please see issue #3030347: Plan to clean process issue queue