With current dev i experience a ajax facets block issue that is not there without ajax.

How to reproduce:

  • Have content types "event" and "organisation"
  • Have a view that lists both types, with an optional context from path like view/%type, so we have view/event, view/organisation, and view/all
  • Have one facet block based on an event field and one based on an organisation field for that view page
  • go to view/organisation (so the view context "content type" is "organisation")

expected:

  • on view/organisation, only facets from type "organisation" are shown

experienced without ajax:

  • works as expected

experienced with ajax enabled:

  • works as expected on first page load
  • when clicking a facet item: facets block shows facets from event and organisation

So it looks like ajax does not see the "organisation" context.

Issue fork facets-2986981

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

axel.rutz created an issue. See original summary.

hanness’s picture

Issue summary: View changes

slightly updated IS to be clearer and better to reproduce.

hanness’s picture

Issue summary: View changes
larowlan’s picture

The issue here is the views ajax request doesn't pass along the ?f[0]= parameters so the facets url processor doesn't pick up that there are active facets.

Will take a look to see what I can suss out.

larowlan’s picture

Here's how I fixed it

Replace YOUR_MODULE_NAME and YOUR_VIEW_ID as appropriate.


/**
 * Implements hook_views_pre_render.
 */
function YOUR_MODULE_views_pre_render($view) {
  if ($view->id() === 'YOUR_VIEW_ID') {
    $view->element['#attached']['drupalSettings']['views']['ajax_path'] = \Drupal::url('views.ajax', [], [
      'query' => \Drupal::request()->query->all(),
    ]);
  }
}

/**
 * Implements hook_module_implements_alter().
 */
function YOUR_MODULE_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'views_pre_render') {
    $group = $implementations['YOUR_MODULE'];
    unset($implementations['YOUR_MODULE']);
    // We need to go after views module.
    $implementations['YOUR_MODULE'] = $group;
  }
}
borisson_’s picture

@larowlan: is that something that we should include in the facets module as well?

hanness’s picture

thanks larowlan!

@borisson_: i think it should go into facets, as view contexts are a common use case (and i remember that it was discovered months ago in the ajax facets issue, but not as a blocker).

we currently discovered that facets and domain access does not work probably together as well. in this case the facets show all counts and items as if there is no domain access - similar to this issue. but it appears independent from ajax, so maybe not related to this.
currently it is not that important for us, we will look into it later.

larowlan’s picture

is that something that we should include in the facets module as well?

Unfortunately, due to the way views uses this, I'm not sure if it can.

See the issue is that whilst views keeps ajax settings per view, in the case of the ajax path its a single value for the whole page.

Now I guess we could argue that any view on that page should pass along the facet url parameters, but I don't know enough about facets to be able to say whether that is correct.

So if every view on the page that uses ajax would still work if we pass along those params, then yes we can. But if we need to be selective about it, then its probably a per-site thing where the site developer makes the decision with knowledge about what views there are on that page.

If you think it is harmless, I'll roll a patch.

we currently discovered that facets and domain access does not work probably together as well. in this case the facets show all counts and items as if there is no domain access - similar to this issue.

Please open a separate issue, that is unrelated.

geek-merlin’s picture

Issue summary: View changes

(Streamlining the IS).

geek-merlin’s picture

@larowlan: Thanks for your code in #5. It looks though like this code fixes lost query parameters. Any idea how to fix lost context (which is part of the path, not the query parameters)?

larowlan’s picture

Ah, I took 'context' to mean 'active facets', but I assume you're meaning context as in the actual drupal context api. Apologies.

rboedeker’s picture

Thank you very much for digging into this issue and to provide the code for us!
I am facing the issue as well and for me your code works perfekt for "link-facets". I am still facing issues with checkbox facets: If I klick on a checkbox facet, the view is updated as expected, however the facetgroup is getting inactive and the checkbox can not be unselected anymore...

Do you have any idea to fix it ?

nchar’s picture

I solved the problem for my project with this patch.

lukasss’s picture

#13 works for me

rboedeker’s picture

Thank you for Patch #13 ! It looks promissing.
I still have the issue with checkbox facets: Obviously js "checkbox-widget.js" turns the link into a checkbox and disabels all checkboxes belonging to the facet.
If I manually refresh the page the checkboxes are set in the right way and I can klick another checkbox that than triggers the View to refresh the result. However all checkboxes out of the facet are disabled until I manually do a page refresh...

Any idea to get the last step done ?

Siavash’s picture

#13 worked for me, thanks!

matteodem’s picture

Since #13 didn't work for me I created a patch with a new hook called hook_facets_search_api_results_view_preprocess, which allows to set the view arguments (or other adjustments) manually.

geek-merlin’s picture

DamienMcKenna’s picture

Status: Active » Needs review
DamienMcKenna’s picture

Status: Needs review » Needs work

After some testing, this isn't working for me either.

DamienMcKenna’s picture

DamienMcKenna’s picture

Title: Ajax facet block seems to lose views context » Ajax facet block seems to lose Views context (filters, etc)
mstrelan’s picture

Heads up if using #5, this doesn't play nicely with views_ajax_history as that module detects the presence of the ? in the URL to determine whether clean urls are enabled or not.

See #3157331: Non-clean URL path added to views ajax url

jhedstrom’s picture

I just encountered this, and traced the issue to a default argument plugin that uses pretty common logic for getting the current node:

$entity = $this->routeMatch->getParameter('node');

Since that fails on ajax routes (no node parameter), this results in the view losing its contextual filter value.

even the core 'Get Content ID from URL' plugin uses logic like this, so those would fail on ajax requests (see #2769251: Contextual filter don't work with ajax in view.) if they were attempting to load view results as the facets module does.

I couldn't find a decent alternative that is common practice for loading the current entity on ajax requests, but will update this if/when we find a workaround.

jhedstrom’s picture

daveiano’s picture

FileSize
694 bytes

I was facing a similar problem when setting contextual Filters for a view via hook_views_pre_execute(), something like this:

function my_module_views_pre_view(ViewExecutable &$view, &$display_id, &$args) {
  if ($view->id() === 'my_view') {
    $my_argument = get_my_argument();   

    $view->args[0] = implode('+', $my_argument);
  }
}

The Initial page load works, only facets from the filtered results are shown, but If clicking on a facet (ajax enabled) the facet shows everything and forgets the programmatically set contextual filters. I ended up just adding the

$view->preExecute();

call in SearchApiDisplay.php to invoke the hook. See attached patch. Probably also the other methods like pre_view should be executed here or are there any culprits when doing this? So perhaps this fix and a working fix for contextual filters set by URL should do it?

jhedstrom’s picture

We ended up working around this using the path.current service, as that does have the current path (not the ajax request path) of, for instance node/123. From there we added this method to retrieve the object similar to the route match service:

  protected function getEntityFromContext() {
    $url_object = $this->pathValidator->getUrlIfValid($this->currentPathStack->getPath());
    if ($url_object === FALSE) {
      return NULL;
    }
    $entity = NULL;
    $route_parameters = $url_object->getRouteParameters();
    if ($route_parameters && !empty($route_parameters['node'])) {
      $entity = $route_parameters['node'];
      $entity = $this->entityTypeManager->getStorage('node')
        ->load($entity);
    }
    return $entity;
  }

neclimdul’s picture

Status: Needs work » Needs review

I'm not sure what the problems people where running into with this patch. I've been using the patch in #13 in several different types of fairly highly trafficked facet page with ajax views since 04/2019. It seems to work perfectly. at fixing the views context.

It also seems like the most correct fix as its recreating the logic views uses to correctly setup the views arguments:
https://git.drupalcode.org/project/drupal/-/blob/9.2.x/core/modules/view...

So, without knowing how it didn't work for people, I'm not sure how to move this forward. We have to run a number of other patches to get the views ajax working correctly like #3031544: Ajax facet adds q and _wrapper_format to the browser URL and now #3191091: QueryString url_processor broken(ish) for Ajax Views so maybe the problem people have is related to those? There where also other problems when a lot of these reviews happened that have been committed so maybe #13 works better now?

edit: remove unrelated issue link

ac’s picture

The patch in #13 solves the issue described. Some of the other comments are a bit of topic IMO. I would support committing #13

neclimdul’s picture

Version: 8.x-1.x-dev » 2.0.x-dev
FileSize
1.51 KB

broken by #2939710: Add support for "Search API (tags based)" caching in Views and follow ups. No meaningful change.

Still running in production. Still just correctly applying the path logic from views. Any chance of committing it?

ac’s picture

Status: Needs review » Reviewed & tested by the community

Agreed. I have been using this in production for years.

Jeroen Dost’s picture

FileSize
1.55 KB

Reroll for v2.0.6

neclimdul’s picture

AndySipple’s picture

Patch #33 worked for me.
My current use case.
Drupal views with an exposed filter search input and exposed and the filters are exposed as a block and the view is an exposed block.
Ajax turned on for the view using with combination with views ajax history module and this patch.

Now ajax works and respects facets + the views exposed filter yay!

Current markup with inside a paragraph using twig tweaks:

{# Site search view exposed form #}
<div class="search-form-container">
{{ drupal_entity('block', 'site_search_form', check_access=false) }}
</div>
{# Facets #}
<div class="facets-container">
  {{ drupal_block('facet_block:content_type') }}
  {{ drupal_block('facet_block:subject') }}
  {{ drupal_block('facet_block:media') }}
</div>
{# Site search view exposed form #}
{{ drupal_view('site_search', 'site_search_default') }}
burnellw_cit’s picture

joseph.olstad’s picture

@burnellw_cit , patches should be created relative to the module, not your project.

You should also rely on composer to apply properly rolled patches such as patch number 32

https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupa...

joseph.olstad’s picture

@burnellw_cit,
A properly rolled patch looks like this:

diff --git a/src/Plugin/facets/facet_source/SearchApiDisplay.php b/src/Plugin/facets/facet_source/SearchApiDisplay.php
index 017f34f..7eac4b1 100644
--- a/src/Plugin/facets/facet_source/SearchApiDisplay.php
+++ b/src/Plugin/facets/facet_source/SearchApiDisplay.php

Yours was made relative to your project, is incorrect.

diff --git a/modules/contrib/facets/src/Plugin/facets/facet_source/SearchApiDisplay.php b/modules/contrib/facets/src/Plugin/facets/facet_source/SearchApiDisplay.php
index d5b7042d..4a6d2510 100644
--- a/modules/contrib/facets/src/Plugin/facets/facet_source/SearchApiDisplay.php
+++ b/modules/contrib/facets/src/Plugin/facets/facet_source/SearchApiDisplay.php

If you use composer to specify patches you would be able to use correctly rolled patches such as patch #32.

Please review this with esteemed colleagues , for further assistance please reach out to someone on slack in the Drupal channels or on https://drupalchat.me . Your organisation may have to change it's process/build slightly to adhere to build norms.

https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupa...

nickvanboven made their first commit to this issue’s fork.

nickvanboven’s picture

I have created a fork with the changes from #32 and added a check for the route object, this can be null if the request is serialized and used at a other time, we use this to get the view options on cron when processing some jobs.

joseph.olstad’s picture

@nickvanboven, the 2 fails seen in MR 137 comment#40 not related to your changes.

#3358365: HEAD tests failing since March 23, 2023