2

I have a View (let's call it A) that gets the 4 more recent nodes of type News. The News node has a boolean field called IsImportantNews. Since I render the most recent important News (IsImportanNews = true) in another View (B), I'd like to filter out from View A the most recent important News that I already shown in View B.

Eg:

News1 -> date: 02 Mar 2013, IsImportant = false
News2 -> date: 01 Mar 2013, IsImportant = false
News3 -> date: 25 Feb 2013, IsImportant = true
News4 -> date: 21 Feb 2013, IsImportant = false
News5 -> date: 19 Feb 2013, IsImportant = true
News6 -> date: 11 Feb 2013, IsImportant = true

I'd like to show the News3 in the View B (and I can do that easily). I'd like to show News1/2/4/5 in the View A, somewhat filtering out the News3.

Is there a way to do that? I thought about taking the 5 more recent News and than apply some php code to filter out the unwanted News but I can't seem to find a place to put that code without writing a new module. Is there another way to do that?

3 Answers 3

1

hook_views_pre_render() would enable you to filter out results after the query has already been run. Keep in mind that the results that are filtered out are still part of the query, with all the performance ramifications of that. Putting that in a custom module would be how I would do that.

If you don't want a view that's just a filtered version of the IsImportant == TRUE view, you could clone the first view and create a similar one whose only difference is that it returns four more results than the IsImportant == TRUE view. You could then add whatever filtering logic you want, and then limit the display to a certain number of items before rendering.

You may also want to take a look at the Peek Summary module, since it gives some further granularity to number of results returned beyond what Views alone offers.

5
  • It's not quite like that. I have two differents views. The first one just returns the most recent important News, which in my example would be News3. Than I want to build another View that gets the 4 more recents News no matter if they are important or not as long as the most recent and important is filtered out, which means, in my example, returning News1/2/4/5 (right now my view returns News1/2/3/4)
    – Geeo
    Commented Feb 2, 2013 at 23:34
  • Ah, ok. Edited answer.
    – beth
    Commented Feb 3, 2013 at 0:38
  • Thank you, I'm using the hook_views_pre_render() approach that you suggested. I'll let you know.
    – Geeo
    Commented Feb 3, 2013 at 0:58
  • This seems to work even if I get some weird div placement after rendering which doesnt happen when I don't filter out the result in the pre_render. I wonder if just using array_splice on view->result isn't enough.
    – Geeo
    Commented Feb 3, 2013 at 19:39
  • What weird div placement is occurring? What code are you putting inside hook_views_pre_render()?
    – beth
    Commented Feb 3, 2013 at 19:48
0

If the most recent important view was a page view you could use hook_get_page_view() to get the important view from within hook_view_pre_view() of the other most recent view. Then you can check the results of the important view and use those results to add an nid argument that excludes those nids.

However I'm guessing you are using two blocks, in which case that solution won't work.

The most number of results you will need to choose from in the other most recent view is 8. This is in the case that you have to pull out all 4 of the items from the other view.

So set your other most recent view to return 8 results. Also, make sure that the important field is a field of the view.

Then from those 8 results, the first 4 important ones will always be the ones from the other view. So you can loop through the results and display the first 4 results that don't include the first 4 important ones.

There are a number of ways you can strip out the ones from the other view. A couple are: Use hook_views_pre_render() in a custom module and loop through the results and pull out the ones you don't want. For example:

/**
 * Implements hook_views_pre_render().
 */
function MODULE_NAME_views_pre_render(&$view) {
  if ($view->name == 'VIEW_NAME' && $view->current_display == 'DISPLAY_NAME' && !empty($view->result)) {
    $important_count = 0;
    foreach ($view->result as $key => $result) {
      // Exclude the first 4 important results.
      if ($result->IMPORTANT_FIELD_NAME) {
        if ($important_count < 4) {
          unset($view->result[$key]);
        }
        $important_count++;
      }
    }
  }
}

Or you can do it in your theme in template.php like this (I'm assuming you have a HTML list type view, as that would be most semantic):

/**
 * Preprocess variables for list views.
 */
function THEME_NAME_preprocess_views_view_list(&$variables) {
  if ($variables['view']->name == 'VIEW_NAME' && $variables['view']->current_display == 'DISPLAY_NAME') {
    $important_count = 0;
    foreach ($variables['view']->result as $key => $result) {
      // Exclude the first 4 important results.
      if ($result->IMPORTANT_FIELD_NAME) {
        if ($important_count < 4) {
          unset($variables['rows'][$key]);
        }
        $important_count++;
      }
    }
  }
}

You could also do it in the views-view-list.tpl.php (or whichever template file is relevant to your view) template file but that is not recommended. I would recommend the pre_render first then the template.php preprocessor second if you really for some reason have an aversion to making custom modules. The reason being is that the theme is meant for front end display and this is ore of a back end functionality task, which really should be in a module.

2
  • I would strongly discourage putting something that is functional like this, rather than primarily aesthetic, in a theme.
    – beth
    Commented Feb 3, 2013 at 0:35
  • I agree, that's why I said the prerender is the most recommended place to put it. Some people don't really care about what is the best way and prefer not to make custom modules, so there is the other option there.
    – rooby
    Commented Feb 3, 2013 at 1:14
0

You would use a new filter group to achieve this. To use this you would follow the below steps.

The first step would be to add all the filters that you used in the View B but with just the oposite filtering. for example in View B you added a filter say IsImportant = TRUE. then here it would be IsImportant = false. If you have put the date as less then some value then in this case it would be greater than. What this does is create a filter that would return all the values except the one in the View B.

Now we go ahead and create w filter group as shown below

enter image description here

Click on and/or, rearrange

You would get a screen similar to the one below

enter image description here

Click on Create new filter group. which creates a new group and should be shown as below.

enter image description here

From the dropdown that is there in between the two groups you can select the operator AND/OR. In your case I think you would need the AND operator as you would want both the operation to filter it out.

We select the filters that we created for excluding view B in to the second group. So that it would stay as group and filter it out.

A bit more clarity on the Group Filtering.

Let us assume that the first group filters out in the following manner.

  • Published Nodes (AND)
  • Nodes of the type News

Now this would return all the nodes irrespective of if it is important or not.

Now the second group would do the following

  • Nodes without the isImportant = False (OR)
  • Nodes That are Older than X days.

Now this would give us all the nodes that are not important OR are x days old. That means it would return all the nodes that are not important with in x days and would return all the nodes that are older than x days irrespective of if that is important OR not.

Now if we AND these two groups we would get a list of all nodes that are Not Important with in x days and All nodes older than x days irrespective of wether they are important or not.

Now you can sort it with respect to the date and limit the number of entries to 4 or what ever you want it to be.

I hope that is what you are looking for.

Hope that clears it.

5
  • I'm not sure this would work. I don't wanna filter out ALL the News with IsImportant = true in the View B. I just want to filter out the most recent News with IsImportant = true. Only one item. In fact, if you look at my example, the View B would contain News1/2/4/5, where News5 has IsImportant = true. Am I missing something?
    – Geeo
    Commented Feb 3, 2013 at 13:56
  • I have updated my answer please read the last part for more clarity Commented Feb 3, 2013 at 16:38
  • Thank you Mohammed. The problem is that I get the most recent important news in an another way. The View A works this way: Published Nodes AND Nodes of type News Where IsImportant = True Order By Date DESC LIMIT 1 (or, in sql like, TOP 1).
    – Geeo
    Commented Feb 3, 2013 at 19:28
  • With my kind of query it doesnt seem possible to do what you are suggesting, any other ideas?
    – Geeo
    Commented Feb 3, 2013 at 20:10
  • that would indeed be difficult. A simple work around would be to enable the sticky at the top for that one content. and filter it using that. Not sure if your current step would allow that. Otherwise you have to go with some coding. as mentioned in the other solutions. Commented Feb 4, 2013 at 4:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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