6

I'm showing many nodes on a page using a few different Views blocks with Panels.

For example there is a "Top Story" block that shows the latest sticky article. Then there are blocks for certain Sections (taxonomy) and important Special Sections (another taxonomy).

A node can appear in both blocks if it has a Section (say, Culture), a Special Section (News) and it may also be Sticky (so it's up in the Top story block too).

The problem here is that I can't just utilize offsets to hide things, but would need something that excludes nodes from later views that have already been shown. Older sticky nodes naturally should push down to their respected blocks when newer Nodes come etc.

Another way to put it:

Let's say we have Views, A, B, C and D. If a node is already in A, it wouldn't show up in B, C and D. If it's shown in B, it would not show up in C & D. It should be hierarchical from "promotion" style blocks to more simple listings when going lower on the page.

Is there any ready solution that would help me achieve this? I'm familiar with module coding, hooks etc so that sort of solutions are open to me as well.

7

You could load and display each view in your template. For each view you will have to get a list of nid values that you then will pass on as argument to the next view in line.

For this to work you should setup a Contextual Filter of type Content: nid and configure it to allow multiple values and exclude supplied nids.

configure contextual filter

In your template your could then do something like this:

// load and display view A
$viewA = views_get_view('VIEW_A');
$viewA->execute();
// get all nids from the result 
foreach ($viewA->result as $result):
   $nids[] = $result->nid;
endforeach;
// render first view
print $viewA->render();

// now load view B
$viewB = views_get_view('VIEW_B');
// set arguments for view
$viewB->set_arguments(array(implode(",", $nids)));
// execute view
$viewB->execute();
// render
print $viewB->render();

If you would like to use just one view with multiple displays, you could use set_display() to select the display that should be used:

$view = views_get_view('VIEW');
$view->set_display('VIEW_DISPLAY_ID');
$view->execute();
4

So given your example (a view with displays A, B, C and D), this is how I would accomplish what you're proposing.

  1. Add an nid field to each of the displays (except D).
  2. Add a nid contextual filter to each display (except A).
  3. For each contextual filter, selected "Provide default value" with Type: "PHP Code" and enter the following PHP Code:

    $nids = array();
    // This is written for display 'D' to illustrate how you could compile a list
    // of all previous nids. Display 'C' would check 'A' and 'B', while 'B' would
    // only need to check 'A' (thus eliminating the need for the first foreach).
    foreach (array('A', 'B', 'C') as $display_name) {
      $rows = views_get_view_result('view_name', $display_name);
      foreach($rows as $row) {
        $nids[] = $row->nid;
      }
    }
    return implode('+', $nids);
    
  4. Under "More" check both "Allow multiple values" and "Exclude".

  • Thanks for this, I was able to adapt it for my use case. One additional thing I had to do was check 'Allow multiple values' under "More" as well. – Vincent Mar 29 '17 at 21:01
1

i see 2 ways to do this, hoping others can see better ones :)

A dirty one would be with Javascript: add to each views the displayed nodes nids in classes, then gather them with JS and hide them from other views.

A more complex but cleaner one would be with args and PhP: you have to double each views with one rendering only nids like that : 1, 2, 3, 4.... Then you use a nodes:nid contextual filter, provide a default value in PhP and then use Views get results to have the nodes to exclude.

Without any further informations on your views that's the only ways I see how to do this :)

PS: when you choose a solution, don't hesitate to ask me for details :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.