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