Skip to main content

To assist in finding possible solutions some of the queries that I made include:

  • Drupal 9 pager with items_per_page
  • Drupal 9 pager merged with exposed form items_per_page

 

I wanted to resolve this issue through the theme file rather than in a custom module.  While most of the time my preference is to create a custom module, the project I'm working at the moment we are working to minimal or no custom modules.  Subsequently, solutions need to be managed via theme file.

 

How did I resolve this using the theme?

I added a hook template_preprocessor_pager function.

/**
 * template_preprocess_pager
 *
 * @param array $variables
 *
 */
function themename_preprocess_pager(&$variables) {

  $view_id = 'magazine';

  $view = \Drupal\views\Views::getView($view_id);
  $view->initHandlers();
  $form_state = new \Drupal\Core\Form\FormState();
  $form_state->setFormState([
    'view' => $view,
    'display' => $view->display_handler->display,
    'exposed_form_plugin' => $view->display_handler->getPlugin('exposed_form'),
    'method' => 'get',
    'rerender' => TRUE,
    'no_redirect' => TRUE,
    'always_process' => TRUE, // This is important for handle the form status.
  ]);

  $variables['sort'] = $form;
}

 

As you will se in this solution, not only did prepare the exposed form for the pager, but I also 

Altered the drop down list, so rather than displaying ## numbers only ie. 5, 10, 25, 50... we wanted to display the number with a label.  Therefore becoming 

  • 5 results per page
  • 10 results per page
  • 25 results per page
  // alter the options so the items_per_page title is added to the output
  foreach ($form['items_per_page']['#options'] as $key => $option) {
    $form['items_per_page']['#options'][$key] = $option . ' ' . $form['items_per_page']['#title'];
  }

Also as the theme was managed via Tailwind, I needed to tweak the class.  The class needed to include

  • tw-text-blue-dark
  • tw-text-sm
  • tw-w-52
$form['#attributes']['class'] = ['tw-text-blue-dark',
                                   'tw-text-sm',
                                   'tw-w-52'];

Finally, remove the label from display.  While I could set the id in css to hidden, I wanted to have nothing displayed at all.

$form['items_per_page']['#title'] = '';

 

Complete solution

/**
 * template_preprocess_pager
 *
 * @param array $variables
 *
 */
function themename_preprocess_pager(&$variables) {

  $view_id = 'magazine';

  $view = \Drupal\views\Views::getView($view_id);
  $view->initHandlers();
  $form_state = new \Drupal\Core\Form\FormState();
  $form_state->setFormState([
    'view' => $view,
    'display' => $view->display_handler->display,
    'exposed_form_plugin' => $view->display_handler->getPlugin('exposed_form'),
    'method' => 'get',
    'rerender' => TRUE,
    'no_redirect' => TRUE,
    'always_process' => TRUE, // This is important for handle the form status.
  ]);

  $form = \Drupal::formBuilder()->buildForm('Drupal\views\Form\ViewsExposedForm', $form_state);
  // alter the options so the items_per_page title is added to the output
  foreach ($form['items_per_page']['#options'] as $key => $option) {
    $form['items_per_page']['#options'][$key] = $option . ' ' . $form['items_per_page']['#title'];
  }
  $form['#attributes']['class'] = ['tw-text-blue-dark',
                                   'tw-text-sm',
                                   'tw-w-52'];
  $form['items_per_page']['#title'] = '';

  $variables['sort'] = $form;
}

 

A few other tips

You can also set #access to false to prevent fields from rendering.

$form = \Drupal::formBuilder()->buildForm('\Drupal\views\Form\ViewsExposedForm', $form_state);
// Hide unnecessary fields.
$form['sort_by']['#access'] = false;
$form['items_per_page']['#access'] = false;

Or hiding the fields that also requires css

$form['search_fulltext']['#type'] = 'hidden';
$form['sort_by']['#type'] = 'hidden';
$form['actions']['#type'] = 'hidden';

And then in your theme CSS:

.form-type-hidden {
  display: none;
}