Note: This could be an issue in Views itself; I found #2742565: Pagination breaks filtering by exposed filter and #2718697: EntityAutocomplete element cannot handle GET input values, but am still seeing the issue using core 8.1.2.

I have created a calendar view of items, along with an exposed filter of taxonomy terms associated with those items. On the default week, month, etc. displays (with no route argument), I can successfully use the exposed filter options (which add a query string to the base path).

However, the Previous/Next pagers are not passed the query string for the filtered items, so when I use the pagers I lose the filters on the display (though the option itself in my exposed remains selected).

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

akalata created an issue. See original summary.

akalata’s picture

As a temporary workaround, I've created the following preprocess function in a custom module, in case anyone else is interested:

/**
 * Implements hook_preprocess_HOOK for the calendar_pager template.
 */
function mymodule_preprocess_calendar_pager(&$variables) {
  // Check to see if a query string exists
  $current_uri = \Drupal::request()->getRequestUri();
  $uri_parts = explode('?', $current_uri);
  if (isset($uri_parts[1])) {
    // If a query string exists, set it as an option on the pager links.
    $query = urldecode($uri_parts[1]);
    $query_parts = explode('=', $query);
    foreach ($variables['items'] as $key => $item) {
      if (is_array($item) && !empty($item['url'])) {
        $variables['items'][$key]['url']->setOption('query', [$query_parts[0] => $query_parts[1]]);
      }
    }
  }
}

Unfortunately, this fix only works when AJAX paging is NOT enabled.

akalata’s picture

I also want to share a related workaround (that is almost certainly a Views issue), where submitting the exposed filters form while on a paged-to page (ie. /month/201607) reverts back to the basic /month path, without the routing argument.

/**
 * Implements hook_form_FORM_ID_alter()
 */
function mymodule_form_views_exposed_form_alter(&$form, &$form_state, $form_id) {
  // Update submit #action to include current pager arguments.
  switch ($form['#id']) {
    case 'views-exposed-form-id-1':
    case 'views-exposed-form-id-2':
      $form['#action'] = \Drupal::service('path.current')->getPath();
      break;
  }
}
sukanya.ramakrishnan’s picture

Please review this patch when you get a chance, the pager urls were missing the filters!

sukanya.ramakrishnan’s picture

Status: Active » Needs review
jhedstrom’s picture

Status: Needs review » Reviewed & tested by the community

I've confirmed the issue manually, and confirmed the patch in #4 retains any exposed filter values on the pager links.

geertvd’s picture

Status: Reviewed & tested by the community » Fixed

Sorry for the delay on this one, committed to 8.1-1.x. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

jeremylichtman’s picture

Note that #4 above still does not address the issue of "select multiple" filters (i.e. url param = ...&foo[]=bar&foo[]=buzz).

Although that may be an issue with views, rather than the calendar module, per se, since the values for the array param are already munged by the time they are passed through to the pager class.

I've created a version of the code in #2 that deals with the case above, here: https://www.drupal.org/node/2901061#comment-12215373

nwoodland’s picture

I'm still encountering this issue even though the patch from #4 appears to be included in my version of dev. As a workaround I took the code from #2 and updated it to work with more than one exposed filter. Here's the code in case this helps anyone else:

/**
 * Implements hook_preprocess_HOOK for the calendar_pager template.
 */
function ak_module_preprocess_calendar_pager(&$variables) {
  $current_uri = \Drupal::request()->getRequestUri();
  $uri_parts = explode('?', $current_uri);
  if (isset($uri_parts[1])) {
    $all_queries_string = urldecode($uri_parts[1]);
    $queries_strings = explode('&', $all_queries_string);
    $queries_arrays = [];
    foreach ($queries_strings as $queries_string) {
      $query_parts = explode('=', $queries_string);
      $queries_arrays[$query_parts[0]] = $query_parts[1];
    }
    foreach ($variables['items'] as $key => $item) {
      if (is_array($item) && !empty($item['url'])) {
        $variables['items'][$key]['url']->setOption('query', $queries_arrays);
      }
    }
  }
}