Problem/Motivation

View exposed filters and contextual filters cannot be used together. The contextual filter is ignored when the exposed filters are used.

Steps to reproduce

Create a View with both exposed filters and contextual filters. Try to use the exposed filters.

Proposed resolution

Pass the existing contextual filter arguments to the View when exposed filters are used.

Remaining tasks

Finalize implementation.

User interface changes

None except that the filters will work as expected.

API changes

None.

Data model changes

None.

Release notes snippet

Issue fork drupal-2821962

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

screon created an issue. See original summary.

screon’s picture

Title: Views exposed filter in block don't combine with contextual filters » Views exposed filters don't combine with contextual filters when using exposed form in block
sukanya.ramakrishnan’s picture

I am facing a similar issue. What i am seeing is that, in your example. the 'webinar' value is changing to 'all' so the contextual filter doesnt get applied.

Debugged a bit further and it seems that the request attributes are lost. (The arguments are got from the '_raw_variables' attribute from the request) Not sure why that is happening. Bumping the issue to major so someone can take a look.

Thanks
Sukanya

sukanya.ramakrishnan’s picture

Priority: Normal » Major
nedjo’s picture

Priority: Major » Normal

This issue describes two bugs that are related but slightly different.

Both likely originate in ViewExecutable::getUrl(), which is called by ViewsExposedForm::buildForm() to set the #action key, which determines the path that the exposed form submits to.

In that method, the URL info is returned if there isn't a path or if no arguments are fed in. See the following lines:

  // Don't bother working if there's nothing to do:
  if (empty($path) || (empty($args) && strpos($path, '%') === FALSE)) {
    return $display_handler->getUrlInfo();
  }

Otherwise, for every argument that isn't fed in, a default parameter is set. See the following lines:

    if (empty($args)) {
      // Try to never put % in a URL; use the wildcard instead.
      if ($id && !empty($this->argument[$id]->options['exception']['value'])) {
        $parameters[$variable_name] = $this->argument[$id]->options['exception']['value'];
      }
      else {
        // Provide some fallback in case no exception value could be found.
        $parameters[$variable_name] = '*';
      }
    }

So what appears to happen on a page that has both contextual filters and exposed filters is and a path that includes an argument, such as node/%node/example:

  • On the initial page load, any contextual filters that don't have values from the URL get their fallback behaviours triggered (those specified in "When the filter value is NOT in the URL").
  • However, the path the exposed form submits to has values appended to the URL for each contextual filter (by default, /all). So, when the form is submitted (even if no change is made), fallback behaviours are not triggered, leading to different (unexpected) results.

For example, if a contextual filter is set to default to the value of the current user's ID, results will be filtered to the current user for the first page load, but after the filter form is submitted the results will be for all users.

joegl’s picture

I am also having the same issue. I have a view with a path of:

store/category/%/%

With exposed filters for sorting options in a block. When I have "all" as an exception in the contextual filter, the exposed filters submits to:

store/category/all?sort_by=...

With "all" removed from the exceptions, the exposed filters form submits to:

store/category/%2A/%2A

It doesn't matter what arguments I have, it always redirects to "all" or %2A.

mroycroft’s picture

Version: 8.2.0 » 8.5.x-dev
StatusFileSize
new10.5 KB

This still happens in the latest dev version of Drupal 8.

Here is a patch with a test that demonstrates the issue. A follow-up patch with the proposed fix included will be posted shortly.

mroycroft’s picture

Here's a patch with the proposed fix.

mroycroft’s picture

Status: Active » Needs review
damontgomery’s picture

When we added this patch, we got critical errors when the argument values were null. I tried to update this along these lines,

    // Pass in the arguments to the exposed form block.
    if ($view->hasUrl()) {
      $args = [];
      foreach ($view->getHandlers('argument') as $argument_name => $argument) {
        /** @var \Drupal\views\Plugin\views\argument\ArgumentPluginBase $argument */
        if (!is_null($view->argument[$argument_name]->getValue())) {
          $args[] = $view->argument[$argument_name]->getValue();
        }
      }

      $form['#action'] = empty($args) ? $view->getUrl()->toString() : $view->getUrl($args)->toString();
    }
    else {
      $form['#action'] = Url::fromRoute('<current>')->toString();
    }

If you try to call $view->getUrl with an empty array, you don't get the url back, so there is a check for that as well.

Unfortunately, this doesn't seem to address our issue and I'll have to keep digging. By the time we load this form, our URL parameter has been lost from the view argument.

damontgomery’s picture

It doesn't address this issue, but we are going with the following approach.

Use the exposed form in the view (not as a block)
Add facet blocks to the view header (Rendered Content - Block)
Wrap the two together in the view template. There is a `header` and an `exposed` variable to work with

We originally wanted to split the exposed filter into a block for flexibility in theming, but moving everything into the view seems viable as well and doesn't have the issue mentioned above. I'm not sure that this is the same issue as what others were mentioning, but there aren't many tickets I could find and maybe this will help someone else who has a similar issue.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

geek-merlin’s picture

@damontgomery #16;:
> When we added this patch, we got critical errors when the argument values were null.

Thanks for the report! Alas, without a backtrace and further info we can only guess if this is a problem of this patch or of your site. This info is important.

Wisamx’s picture

I didn't know this problem is 2 years old!

I have asked a question related to this problem trying to solve it by altering exposed form or hook into views pre render, But I failed.

https://drupal.stackexchange.com/questions/264262/setting-exposed-filter...

Hope there is a solution.

geek-merlin’s picture

The patch in #8 looks good to me but after trying in can confirm there are issues with it :-(.
Here's the backtrace in our case:

The website encountered an unexpected error. Please try again later.Symfony\Component\Routing\Exception\InvalidParameterException: Parameter "arg_0" for route "view.h4c_map.map" must match "[^/]++" ("" given) to generate a corresponding URL. in Drupal\Core\Routing\UrlGenerator->doGenerate() (line 204 of core/lib/Drupal/Core/Routing/UrlGenerator.php).

Drupal\Core\Routing\UrlGenerator->getInternalPathFromRoute('view.h4c_map.map', Object, Array, Array) (Line: 293)
Drupal\Core\Routing\UrlGenerator->generateFromRoute('view.h4c_map.map', Array, Array, 1) (Line: 105)
Drupal\Core\Render\MetadataBubblingUrlGenerator->generateFromRoute('view.h4c_map.map', Array, Array, ) (Line: 753)
Drupal\Core\Url->toString() (Line: 122)
Drupal\views\Form\ViewsExposedForm->buildForm(Array, Object)
call_user_func_array(Array, Array) (Line: 514)
Drupal\Core\Form\FormBuilder->retrieveForm('views_exposed_form', Object) (Line: 271)
Drupal\Core\Form\FormBuilder->buildForm('views_exposed_form', Object) (Line: 135)
Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm(1) (Line: 2569)
Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks() (Line: 34)
Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build() (Line: 203)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func('Drupal\block\BlockViewBuilder::preRender', Array) (Line: 378)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 450)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 124)
Drupal\blockgroup\Plugin\Block\BlockGroup->build() (Line: 203)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func('Drupal\block\BlockViewBuilder::preRender', Array) (Line: 378)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 450)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 490)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 118)
__TwigTemplate_5739f58f4e0d1f47bd1e953fd2526475a97d2cdbe6a91a1bca565a98be44f522->block_sidebar_first(Array, Array) (Line: 215)
Twig_Template->displayBlock('sidebar_first', Array, Array) (Line: 73)
__TwigTemplate_5739f58f4e0d1f47bd1e953fd2526475a97d2cdbe6a91a1bca565a98be44f522->block_main(Array, Array) (Line: 215)
Twig_Template->displayBlock('main', Array, Array) (Line: 63)
__TwigTemplate_d84548ac530e850f0e4cfd1162ead857057599dfef445fba2733bfa582a65887->doDisplay(Array, Array) (Line: 432)
Twig_Template->displayWithErrorHandling(Array, Array) (Line: 403)
Twig_Template->display(Array, Array) (Line: 50)
__TwigTemplate_5739f58f4e0d1f47bd1e953fd2526475a97d2cdbe6a91a1bca565a98be44f522->doDisplay(Array, Array) (Line: 432)
Twig_Template->displayWithErrorHandling(Array, Array) (Line: 403)
Twig_Template->display(Array) (Line: 411)
Twig_Template->render(Array) (Line: 64)
twig_render_template('themes/contrib/enzian/src/templates/system/page--map.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('page', Array) (Line: 437)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 490)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 84)
__TwigTemplate_cdeba3f10bdc34526b86687e71a4a8ed261ad5e6729461146d02b3f2683427d2->doDisplay(Array, Array) (Line: 432)
Twig_Template->displayWithErrorHandling(Array, Array) (Line: 403)
Twig_Template->display(Array) (Line: 411)
Twig_Template->render(Array) (Line: 64)
twig_render_template('themes/contrib/bulma/templates/system/html.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('html', Array) (Line: 437)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 147)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 582)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 148)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object) (Line: 156)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 664)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
hanness’s picture

Status: Needs review » Needs work

The patch in #8 looks good to me but after trying in can confirm there are issues with it :-(.

geek-merlin’s picture

OK for the records: when i backtrace in ViewsExposedForm::buildForm, i see
a) when the exposed form is rendered inside the view, it sees the argument
b) when the exposed form is rendered in the block, it seems not to see the argument

see below both backtraces.

array:31 [▼
  "30: Drupal\views\Form\ViewsExposedForm->buildForm()" => array:2 [▶]
  "29: call_user_func_array()" => array:1 [▶]
  "28: Drupal\Core\Form\FormBuilder->retrieveForm()" => array:2 [▶]
  "27: Drupal\Core\Form\FormBuilder->buildForm()" => array:2 [▶]
  "26: Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm()" => array:1 [▶]
  "25: Drupal\views\ViewExecutable->build()" => array:1 [▶]
  "24: Drupal\views\Plugin\views\display\PathPluginBase->execute()" => array:1 [▶]
  "23: Drupal\views\Plugin\views\display\Page->execute()" => array:1 [▶]
  "22: Drupal\views\ViewExecutable->executeDisplay()" => array:2 [▶]
  "21: Drupal\views\Element\View::preRenderViewElement()" => array:2 [▶]
  "20: call_user_func()" => array:1 [▶]
  "19: Drupal\Core\Render\Renderer->doRender()" => array:2 [▶]
  "18: Drupal\Core\Render\Renderer->render()" => array:2 [▶]
  "17: Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()" => array:1 [▶]
  "16: Drupal\Core\Render\Renderer->executeInRenderContext()" => array:2 [▶]
  "15: Drupal\Core\Render\MainContent\HtmlRenderer->prepare()" => array:2 [▶]
  "14: Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse()" => array:2 [▶]
  "13: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()" => array:2 [▶]
  "12: call_user_func()" => array:1 [▶]
  "11: Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()" => array:2 [▶]
  "10: Symfony\Component\HttpKernel\HttpKernel->handleRaw()" => array:2 [▶]
  " 9: Symfony\Component\HttpKernel\HttpKernel->handle()" => array:2 [▶]
  " 8: Drupal\Core\StackMiddleware\Session->handle()" => array:2 [▶]
  " 7: Drupal\Core\StackMiddleware\KernelPreHandle->handle()" => array:2 [▶]
  " 6: Drupal\page_cache\StackMiddleware\PageCache->pass()" => array:2 [▶]
  " 5: Drupal\page_cache\StackMiddleware\PageCache->handle()" => array:2 [▶]
  " 4: Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()" => array:2 [▶]
  " 3: Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()" => array:2 [▶]
  " 2: Stack\StackedHttpKernel->handle()" => array:2 [▶]
  " 1: Drupal\Core\DrupalKernel->handle()" => array:2 [▶]
  " 0: main()" => array:2 [▶]
]
array:60 [▼
  "59: Drupal\views\Form\ViewsExposedForm->buildForm()" => array:2 [▶]
  "58: call_user_func_array()" => array:1 [▶]
  "57: Drupal\Core\Form\FormBuilder->retrieveForm()" => array:2 [▶]
  "56: Drupal\Core\Form\FormBuilder->buildForm()" => array:2 [▶]
  "55: Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm()" => array:2 [▶]
  "54: Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks()" => array:1 [▶]
  "53: Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build()" => array:1 [▶]
  "52: Drupal\block\BlockViewBuilder::preRender()" => array:2 [▶]
  "51: call_user_func()" => array:1 [▶]
  "50: Drupal\Core\Render\Renderer->doRender()" => array:2 [▶]
  "49: Drupal\Core\Render\Renderer->doRender()" => array:2 [▶]
  "48: Drupal\Core\Render\Renderer->render()" => array:2 [▶]
  "47: Drupal\blockgroup\Plugin\Block\BlockGroup->build()" => array:1 [▶]
  "46: Drupal\block\BlockViewBuilder::preRender()" => array:2 [▶]
  "45: call_user_func()" => array:1 [▶]
  "44: Drupal\Core\Render\Renderer->doRender()" => array:2 [▶]
  "43: Drupal\Core\Render\Renderer->doRender()" => array:2 [▶]
  "42: Drupal\Core\Render\Renderer->render()" => array:2 [▶]
  "41: Drupal\Core\Template\TwigExtension->escapeFilter()" => array:2 [▶]
  "40: __TwigTemplate_5739f58f4e0d1f47bd1e953fd2526475a97d2cdbe6a91a1bca565a98be44f522->block_sidebar_first()" => array:2 [▶]
  "39: Twig_Template->displayBlock()" => array:2 [▶]
  "38: __TwigTemplate_5739f58f4e0d1f47bd1e953fd2526475a97d2cdbe6a91a1bca565a98be44f522->block_main()" => array:2 [▶]
  "37: Twig_Template->displayBlock()" => array:2 [▶]
  "36: __TwigTemplate_d84548ac530e850f0e4cfd1162ead857057599dfef445fba2733bfa582a65887->doDisplay()" => array:2 [▶]
  "35: Twig_Template->displayWithErrorHandling()" => array:2 [▶]
  "34: Twig_Template->display()" => array:2 [▶]
  "33: __TwigTemplate_5739f58f4e0d1f47bd1e953fd2526475a97d2cdbe6a91a1bca565a98be44f522->doDisplay()" => array:2 [▶]
  "32: Twig_Template->displayWithErrorHandling()" => array:2 [▶]
  "31: Twig_Template->display()" => array:2 [▶]
  "30: Twig_Template->render()" => array:2 [▶]
  "29: twig_render_template()" => array:2 [▶]
  "28: Drupal\Core\Theme\ThemeManager->render()" => array:2 [▶]
  "27: Drupal\Core\Render\Renderer->doRender()" => array:2 [▶]
  "26: Drupal\Core\Render\Renderer->render()" => array:2 [▶]
  "25: Drupal\Core\Template\TwigExtension->escapeFilter()" => array:2 [▶]
  "24: __TwigTemplate_cdeba3f10bdc34526b86687e71a4a8ed261ad5e6729461146d02b3f2683427d2->doDisplay()" => array:2 [▶]
  "23: Twig_Template->displayWithErrorHandling()" => array:2 [▶]
  "22: Twig_Template->display()" => array:2 [▶]
  "21: Twig_Template->render()" => array:2 [▶]
  "20: twig_render_template()" => array:2 [▶]
  "19: Drupal\Core\Theme\ThemeManager->render()" => array:2 [▶]
  "18: Drupal\Core\Render\Renderer->doRender()" => array:2 [▶]
  "17: Drupal\Core\Render\Renderer->render()" => array:2 [▶]
  "16: Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()" => array:1 [▶]
  "15: Drupal\Core\Render\Renderer->executeInRenderContext()" => array:2 [▶]
  "14: Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse()" => array:2 [▶]
  "13: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()" => array:2 [▶]
  "12: call_user_func()" => array:1 [▶]
  "11: Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()" => array:2 [▶]
  "10: Symfony\Component\HttpKernel\HttpKernel->handleRaw()" => array:2 [▶]
  " 9: Symfony\Component\HttpKernel\HttpKernel->handle()" => array:2 [▶]
  " 8: Drupal\Core\StackMiddleware\Session->handle()" => array:2 [▶]
  " 7: Drupal\Core\StackMiddleware\KernelPreHandle->handle()" => array:2 [▶]
  " 6: Drupal\page_cache\StackMiddleware\PageCache->pass()" => array:2 [▶]
  " 5: Drupal\page_cache\StackMiddleware\PageCache->handle()" => array:2 [▶]
  " 4: Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()" => array:2 [▶]
  " 3: Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()" => array:2 [▶]
  " 2: Stack\StackedHttpKernel->handle()" => array:2 [▶]
  " 1: Drupal\Core\DrupalKernel->handle()" => array:2 [▶]
  " 0: main()" => array:2 [▶]
]

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

5n00py’s picture

After few hours of digging found some useful details.

\Drupal\views\Routing\ViewPageController::handle

In this controller Views build args that will be passed to Views executable.

In case of bock we don't have this piece of work, views executed without arguments...

I write simple patch to fix issue on my sites. This problem should be fixed in proper way:

  • tests
  • Correct DI
  • Don't repeat code.

Currently (last patch) tests are incorrect. Test view shouldn't provide default value for contextual filter because it pull arg from current route instead of views path.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

marcuschristopher’s picture

I stumbled over this only recently (working with 8.6.14), when combining a contextual filter for taxonomy terms with additional exposed filters. And it took me almost two days to finally find this issue (didn't know, if this was actually a bug or if I was doing anything wrong). Are there any news on this?

Anyway, thanks @damontgomery: The workaround in #11 turned out to be a great idea. Not sure, what was meant by "facet blocks"... I solved the issue by using a template file views-view--taxonomy-term.html and adding the sidebar with...

<div class="view-filters form-group">
  {{ exposed }}
</div>

there. Thanks for the suggestion.

N1ghteyes’s picture

It is possible to use a form alter to fix the form action for exposed filters. I'm using Better Exposed filters, but you can remove that check if you like.

//my_module.module
/**
 * Implements hook_form_alter().
 * @param $form
 * @param FormStateInterface $form_state
 * @param $form_id
 */
function hook_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
    $current_path = \Drupal::service('path.current')->getPath();
    if($form_id == 'views_exposed_form'){
        if(in_array('bef-exposed-form', $form['#attributes']['class'])){
            //force the form action to match the current path - used to fix broken exposed filters when using contextual links
            $form['#action'] = $current_path;
        }
    }
}
N1ghteyes’s picture

It is possible to use a form alter to fix the form action for exposed filters. I'm using Better Exposed filters, but you can remove that check if you like.

//my_module.module
/**
 * Implements hook_form_alter().
 * @param $form
 * @param FormStateInterface $form_state
 * @param $form_id
 */
function hook_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
    $current_path = \Drupal::service('path.current')->getPath();
    if($form_id == 'views_exposed_form'){
        if(in_array('bef-exposed-form', $form['#attributes']['class'])){
            //force the form action to match the current path - used to fix broken exposed filters when using contextual links
            $form['#action'] = $current_path;
        }
    }
}
beanjammin’s picture

Until there's a fix N1ghteyes' approach of correcting the form action via hook_form_alter() provides full functionality with the exposed filter in a block.

stevenlafl’s picture

Patch #19 causes taxonomy feeds to show no content. D8.6.16

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

stevenlafl’s picture

A followup to this, I used patch #19 under buildForm of ViewsExposedFilter, I replaced the

$view->setArguments($args)

with

$view->setArguments(array_merge(array_filter($view->args, function($value) { return !is_null($value); }), $args));

and that appears to have solved it.

More information: Drupal 8.6.16. Using the Panels IPE to change the Block configuration of a Taxonomy Feed with contextual filter "Has Taxonomy ID". The "Content: Has Taxonomy ID" shows up in the Block configuration with 2 options: "" (blank, with a value of @panelizer.entity_context:entity, the contextual filter) and "- None -". When I switch it to "- None -", the page errors out with "Parameter "arg_0" for route "view.taxonomy_term.feed_1" must match "[^/]++" ("" given) to generate a corresponding URL."

I don't know whether this is a problem with panels/panelizer or core.

That said, even more information about how the value of "- None -" causes that error:
panels_ipe provides "Content: Has Taxonomy Term" field by using addContextAssignmentElement. Upon saving, I get "Illegal choice detected" This is because the ContextDefinition does not have a label. To explain: the #options array provided to panels_ipe is ["@panelizer.entity_context:entity": null] As such, when it gets to FormValidator, the validation fails on !isset($options[$elements['#value']]) fails because isset checks if the element is in the array AND is NOT null. In this case, it is null. It still saved in my case, and crashed the page on reload with a WSOD. The null value exists in arg_0 causing the above error.

If anyone else is having this problem, the above tweak to #19 fixed my issue.

edurenye’s picture

The patch does not apply to 8.7.x and up,

stevenlafl’s picture

My bad @edurenye, I meant to do that months ago.
Here it is.

ronaldtebrake’s picture

From a functional perspective both #19 and #27 work for me.

+++ b/core/modules/views/src/Form/ViewsExposedForm.php
@@ -67,6 +67,9 @@ class ViewsExposedForm extends FormBase {
+    $view->setArguments(array_merge(array_filter($view->args, function($value) { return !is_null($value); }), $args));

I personally believe it's a panels/contrib module problem.

Attached a notest path for 8.8

marcuschristopher’s picture

Thanks a lot: The patch from #30 solved the problem for me. (Drupal 8.8.4)

ravi.shankar’s picture

StatusFileSize
new2.09 KB
new707 bytes

Here I am trying to fix the failed tests.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

nikitagupta’s picture

StatusFileSize
new2.98 KB
hardik_patel_12’s picture

Status: Needs work » Needs review
StatusFileSize
new2.97 KB
new635 bytes

Solving failed test cases.

Status: Needs review » Needs work

The last submitted patch, 35: 2821962-35.patch, failed testing. View results

rolki’s picture

This patch is not ideal and creates another big issue, see
https://www.drupal.org/project/drupal/issues/3152554
I'll close that related ticket and fix the issue here.

rolki’s picture

rolki’s picture

It should be better now.

hardik_patel_12’s picture

Status: Needs work » Needs review
StatusFileSize
new2.46 KB
new1.67 KB

Solving failed test cases, kindly follow a new patch.

Status: Needs review » Needs work

The last submitted patch, 40: 2821962-40.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

hardik_patel_12’s picture

Status: Needs work » Needs review
StatusFileSize
new2.46 KB
new797 bytes

Kindly follow a new patch , forgot to move $map = $route->hasOption('_view_argument_map') ? $route->getOption('_view_argument_map') : []; inside the if ($route instanceof Route) {.

Kindly follow a new patch.

hudri’s picture

Patch #42 did not work for me (having the exposed filter in a block), contextual filters were gone after the first exposed form submit.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

jeroendegloire’s picture

I confirm that on version 8.9, only the patch in #30 is working.

kivicky’s picture

Nevermind - removing that comment since it was not caused by the same issue.

bobooon’s picture

Patch #42 only works if the view display is a page. Exposed forms in blocks can also be attached to block view displays.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

ratvas’s picture

Although patch provided in #30 fixes the issue described, unfortunately it inadvertently broke the media library (which also uses Views). On version 8.9.16.
I am adding slightly updated patch with 'if' statement around the setArguments() call which still solves the original problem without breaking the media library.

mistrae’s picture

I couldn't apply the #49 patch so I created another one.
I've added some checks for empty args as it can break some functionalities such as title rewriting

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

andysipple’s picture

Reporting this patch causes an issue when using the media library widget. Unable to select images in media library after sorting, filtering, or paging within the media lib widget.

ravi.shankar’s picture

StatusFileSize
new3.17 KB
new2.06 KB

Fixed Drupal CS issue of patch #50.

Status: Needs review » Needs work

The last submitted patch, 53: 2821962-53.patch, failed testing. View results

gillesv’s picture

Patch #53 also breaks Media Library functionality, as mentioned in #49.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

khiminrm’s picture

StatusFileSize
new6.53 KB

I've reviewed the patches and tried to create one which contains different conditions.

khiminrm’s picture

StatusFileSize
new6.51 KB
khiminrm’s picture

After re-testing I see that the patch from #59 doesn't fix the issue.

Update: after re-testing again. It looks like the exposed filters in block work with contextual filter by using the patch from #59. Maybe I had some caching issues localy.

lugir’s picture

Tried patch #42 and #59, still got same error messages after drush cr:

Symfony\Component\Routing\Exception\InvalidParameterException: Parameter "taxonomy_term" for route "view.taxonomy_term.page_1" must match "[^/]++" ("" given) to generate a corresponding URL. in Drupal\Core\Routing\UrlGenerator->doGenerate() (line 203 of core/lib/Drupal/Core/Routing/UrlGenerator.php).
Drupal\Core\Routing\UrlGenerator->getInternalPathFromRoute() (Line: 292)
Drupal\Core\Routing\UrlGenerator->generateFromRoute() (Line: 105)
Drupal\Core\Render\MetadataBubblingUrlGenerator->generateFromRoute() (Line: 765)
Drupal\Core\Url->toString() (Line: 173)
Drupal\views\Form\ViewsExposedForm->buildForm()
call_user_func_array() (Line: 534)
Drupal\Core\Form\FormBuilder->retrieveForm() (Line: 281)
Drupal\Core\Form\FormBuilder->buildForm() (Line: 134)
Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm() (Line: 1253)
...

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

javitan’s picture

Issue summary: View changes
StatusFileSize
new6.44 KB

#59 solves the issue for me using Drupal 9.5.5. I'm using a view with a contextual filter and I'm exposing the filters with Better Exposed Filters. Also the Media Library is working normally. Anyway, I removed an empty if.

javitan’s picture

StatusFileSize
new6.51 KB

Ups, my fault. I fixed my last change. I cleaned buildArgs() function.

liam morland’s picture

Status: Needs work » Needs review
StatusFileSize
new6.51 KB

Re-roll of #64 for 11.x.

This patch is also in the merge request.

needs-review-queue-bot’s picture

Status: Needs review » Needs work

The Needs Review Queue Bot tested this issue.

While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)

liam morland’s picture

Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

There's no issue summary. Please use the standard issue template.

liam morland’s picture

Status: Needs work » Needs review

.

liam morland’s picture

Issue summary: View changes
smustgrave’s picture

Status: Needs review » Needs work
Issue tags: -Needs issue summary update +Needs Review Queue Initiative, +Needs tests

Left some comments on MR.

Will need some test coverage to show the issue.

Hiding patches for clarity.

liam morland’s picture

Thanks; changes in comments committed

rollins’s picture

I tested the code from MR and got the next error:
Fatal error: Type of Drupal\views\Form\ViewsExposedForm::$routeMatch must not be defined (as in class Drupal\Core\Form\FormBase) in /var/www/html/web/core/modules/views/src/Form/ViewsExposedForm.php on line 21

liam morland’s picture

Status: Needs work » Needs review

I have removed using of constructor property promotion which should resolve the $routeMatch error.

Another possibility would be to replace the use of $this->routeMatch with $this->getRouteMatch() and not inject it at all.

smustgrave’s picture

Status: Needs review » Needs work

Thanks for keeping this going

Was previously tagged for tests so moving back to NW for that.

Left a comment about using promotion that should simplify things.

liam morland’s picture

I removed the constructor property promotion because when it is used, the property has a type declared. That type doesn't match the parent and so you get the error shown in #74.

To avoid all this, I just updated the merge request to use ::getRouteMatch().

socialnicheguru’s picture

This was available for Drupal 7, https://www.drupal.org/project/filter_harmonizer

vensires’s picture

Status: Needs work » Reviewed & tested by the community

The changes from the latest MR solved the problem for me. Thank you!
Setting it as RTBC.

lendude’s picture

Status: Reviewed & tested by the community » Needs work

This still needs automated test coverage before it can be committed.

vensires’s picture

In my latest change I allowed the inclusion of parameters with the all value.
Without this change, URLs like /foo/bar/[arg_0]/[arg_1]/[arg_2] throw an exception if [arg_2] has a value but [arg_1] is all.

kevinquillen’s picture

Not sure if this is related to this issue, but I wound up in the same area of code that the patch is addressing but for another reason.

My case: I have a Views REST display with a path of api/v1/foo/bar/%node. It has two contextual filters. The first one uses the URL value to load a node for the contextual filter. The second one uses the currently logged in user.

The admin View UI preview works fine by just passing a node id in "Preview with contextual filters". However, if I am trying to assemble the URL to pass along for a decoupled React app, Views requires the two arguments:

        $view_url = $this->request->getSchemeAndHttpHost() .
          $view->getUrl(
            [
              $node->id(),
              \Drupal::currentUser()->id(),
            ]
          )->toString();

If I visit api/v1/foo/bar/(node id) directly, I get results without needing the additional argument in the URL. If I curl the URL (with an authenticated cookie value from my session) I get a value.

I can alternatively do this:

if ($display_id == 'my_view_id' && !empty($node->id())) {
        $view_url = $this->request->getSchemeAndHttpHost() . Url::fromUserInput('/' . str_replace('%node', $node->id(), $view->getPath()))->toString();
      }

but that is not so great to read or maintain. Should the URL be the equivalent of the path? How is that interpreted?

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.