Programmatically change views pager type or options

Posted by patrick on Fri, 04/21/2017 - 08:12

Suppose you have a view and want to dynamically alter the number of results shown by the view based on the view arguments. ViewExecutable provides a setItemsPerPage() method, so this seems easily done at a first glance, but – as always – the devil is in the details.

If we don't have the ViewExecutable object, yet, the best thing to do is implement a hook provided by the Views module first. Don't do that in your module file as you would with other hooks, but instead create a new file module_name.views_execution.inc in the root folder of your custom module and implement the hook there. Views module will load this file as needed. A good hook to make changes to the pager is hook_views_pre_view(), right at the beginning of the initialization phase.

Another helpful method provided by ViewExecutable is setOffset(), which allows you to modify the offset (e.g. skip the first 2 items of the results).

Important caveat: If you're using a pager plugin, that doesn't use these options, then calls to those methods will have no effect. So if you're using the none pager plugin (i.e. Display all results pager setting in the UI), the view will always show all results, even if you call the setItemsPerPage() method on it. In that case, you need to change to a pager plugin that uses this setting first (e.g. some, which is equivalent to the Display a specified number of items setting in the UI). To do so, we can get the pager option from the display handler using the getOption() method. This will return an array with a type key and an options key. The type value is a string, that contains the name of the pager plugin and the options value is an array that contains all the settings of the pager plugin. After changing this array as needed, we can use the setOption() method to update the pager options. That way, you can also change any other options of pager plugins, that you may need to change. Just modify the options array as needed.

Let's see how this would look in code:

<?php
 
/**
 * @file
 * Hook implementations for hooks provided by Views API.
 */
 
use Drupal\views\ViewExecutable;
 
/**
 * Implements hook_views_pre_view().
 */
function example_views_pre_view(ViewExecutable $view) {
  if ($view->id() == 'example_view' && $view->current_display == 'display_id') {
    // Show only three items. This assumes, that we already use a pager plugin, 
    // that uses this option. Otherwise it wouldn't have any effect.
    $view->setItemsPerPage(3);
 
    // Skip the first 5 items. Again, this assumes, that we already use a 
    // pager plugin, that uses this option. Otherwise it wouldn't have any 
    // effect.
    $view->setOffset(5);
   
    // If we need to change the pager type or other options of the pager, we 
    // need to modify the pager option of the display handler.
    $pager = $view->display_handler->getOption('pager');
 
    // Change the pager plugin. Some will show a specified number of results.
    $pager['type'] = 'some';
   
    // All options used by the plugin are available in $pager['options'].
    // If you want to change them, that's fine. You just need to know the keys.
 
    // Update pager option of the display handler.
    $view->display_handler->setOption('pager', $pager);
  }
}
Systems
Drupal 8