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; }