Problem/Motivation

The facets module breaks all AJAX views pagers even those that do not use facets.

Since the module overrides the base ajaxView method at

  public function onRouteAlter(RouteBuildEvent $event) {
    $collection = $event->getRouteCollection();
    if ($route = $collection->get('views.ajax')) {
      $route->setDefault('_controller', '\Drupal\facets\Controller\FacetsViewsAjaxController::ajaxView');
    }
  }

And the first line in the ajaxView method of the facets module is

$this->facetsRemoveQueryParams($request);

So it does not check if the view even has facets or not, just simply removes the "page" from all ajax views request.

This of course breaks all AJAX views that tries to paginate with AJAX.

Steps to reproduce

- Install the 3.x version of the facets module.
- Add any AJAX enabled view with a pager.
- The pager does not work.

(For example this breaks pagination on media library views as well)

Proposed resolution

Removing that one line
$this->facetsRemoveQueryParams($request);
fixes the issue, but I guess it was there for a reason.
So a better approach could be to detect if the views in question is a search api (or facet containing view) and then conditionally do the removal.
This is new in branch 3.x as I see so 2.x is not affected.

Comments

nagy.balint created an issue. See original summary.

nagy.balint’s picture

Issue summary: View changes
nagy.balint’s picture

Status: Active » Needs work
StatusFileSize
new2.02 KB

Here is a quickfix for the problem.

Of course this will not make it work when facets are present on the view.

But it will fix normal views like the media library which normally has no facets but has to work with ajax most of the time.

herved’s picture

I'm facing the same issue.
I believe this especially shows on Drupal 10.1 as it now passes the page parameter directly (possibly from #956186: Allow AJAX to use GET requests ?)

I would like to understand what that code is doing and why it is there in facets and find a proper fix but I cannot even get ajax facets to work at all...
The only ajax-related test in \Drupal\Tests\facets\FunctionalJavascript\AjaxBehaviorTest doesn't seem to actually use ajax...
Things do not make any sense to me TBH...
PS: I created #3353991: How to make AJAX work with facets 3? (issue with isRenderedInCurrentRequest)

freddy rodriguez’s picture

+1

herved’s picture

I found an issue with patch #3 when accessing /views/ajax:

Warning: array_flip(): Can only flip string and integer values, entry skipped in Drupal\Core\Entity\EntityStorageBase->loadMultiple() (line 278 of core/lib/Drupal/Core/Entity/EntityStorageBase.php).

Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array) (Line: 262)
Drupal\Core\Entity\EntityStorageBase->load(NULL) (Line: 26)
Drupal\facets\Controller\FacetsViewsAjaxController->ajaxView(Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 583)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 166)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 74)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

It needs to check if the view_name param is present.

Kevin Hoffmann’s picture

+1 for the patch

Also as a side note facetsRemoveQueryParams() contains

This only applies when the method is POST.

in its docstring. That being said its not even checking that condition itself and applies also for GET requests on my side. Aside from the fact that we remove keys from $request->query which afaik is related to GET requests to begin with.

herved’s picture

StatusFileSize
new2.04 KB
new541 bytes

@7 Indeed I also noticed this. This commit changed $request->getMethod() === Request::METHOD_POST to $request->isXmlHttpRequest(). Perhaps it wasn't intentional ?
Again, I have no clue how AJAX facets are supposed to work since I can't make them work myself despite trying so I can't even debug or understand what this code is all about.

In the mean time, here is a fix for #6.

jefflogan’s picture

Thanks for the patch, this fixed my issue with the broken pager on ajax views.
+1 RTBC

mkalkbrenner’s picture

AJAX in facets 3.0.x is not yet finished. We waited for https://www.drupal.org/node/3193798

And Drupal now uses a newer symfony version which changed the request parameter handling.

claudiu.cristea’s picture

Status: Needs work » Reviewed & tested by the community

Tested and the error is fixed now.

mkalkbrenner’s picture

Tested and the error is fixed now

Do you mean, that the code in 3.0.x dev works now since due to latest commits and that no further patch is needed. Or did you RTBC this patch here?

Did you test the patch with the latest dev version?

claudiu.cristea’s picture

@mkalkbrenner,

We've applied the patch from #8 against 3.0.0-beta1 and that fixed the bug described in this issue (i.e. all ajax pagers are broken). I've RTBCed this patch because it fixes this issue.

mkalkbrenner’s picture

Status: Reviewed & tested by the community » Needs work

The issue description seems to be redundant to #3225764: Facets doesn't work correctly with views infinite scroll. That issue has been fixed and is already committed to the 3.0.x branch.
So I'm not sure if the patch proposed here is still required or if it needs adjustments due to the changes in 3.0.x-dev. So I won't commit it as it is.

herved’s picture

Hello, thanks for the update.

For me it doesn't work, I tried both the latest 3.0.x (b71823b), and 3.0-beta1 + patch #8 from #3225764.
I'm on core 10.1.4, without views_ajax_get.

It looks like views attempts to get the current page from \Drupal\Core\Pager\PagerParameters::getPagerParameter which retrieves it from $request->query->get('page', ''); while \Drupal\facets\Controller\FacetsViewsAjaxController::facetsRemoveQueryParams removes the page param from $request->query.

mkalkbrenner’s picture

FacetsViewsAjaxController has been introduced by older versions of facets. I wonder if it should be removed entirely.

mkalkbrenner’s picture

The code is about having and removing these GET parameters because Views AJAX based on POST. But nowadays Views AJAX bases on GET.
3.0.x already requires Drupal 10.1. So we should not care about POST anymore.

undersound3’s picture

FYI

After upgrading from drupal 9.5.10 to 10.1.3 facet items were not showing up anymore in the Facet Summary block (not sure if related but writing down here for completeness sake).

I was then updating this module from 2.0.6 to 3.0.0-beta1 to see if it fixed that. It did. But then pagination in a "Media Browser Entity" browser did not work anymore. Applying this patch fixed that problem and now pagination works again.

drupal core: 10.1.3
facets: 3.0.0-beta1
views_infinite_scroll: 2.0.2

not using the views_ajax_get module

strykaizer’s picture

StatusFileSize
new21 KB

Attached patch will remove all leftover ajax stuff specific for facet blocks. There will be no ajax support for facets rendered as a block anymore in 3.x

The way to go when you want facets + ajax is using the new better exposed filters way, see #3394955

mkalkbrenner’s picture

Status: Needs work » Needs review
mkalkbrenner’s picture

Status: Needs review » Reviewed & tested by the community

mkalkbrenner’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

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

energee’s picture

StatusFileSize
new20.77 KB

Rolled against 3.0.0-beta1

wfraga’s picture

@energee

I'm getting this error when applying 3379445-25.patch

Drupal core: 10.1.6
PHP: 8.1.2
Facets: 3.0.0-beta1

Drupal\Component\Plugin\Exception\PluginNotFoundException: The "facets" plugin does not exist. Valid plugin IDs for Drupal\better_exposed_filters\Plugin\BetterExposedFiltersWidgetManager are: default, bef_links, bef_sliders, bef_datepicker, bef_single, bef_hidden, bef in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 53 of core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php).

bramvandenbulcke’s picture

Patch 3379445-25.patch is working fine for me.

@wfraga: is Facets 3.x enabled (installed) on your website?

joseph.olstad’s picture

Friendly nudge to please tag a release.

noregrebt’s picture

Patch 25 as well as dev release fixes the problem for me but breaks the actual facets.

noregrebt’s picture

Using dev release and then re-saving each facet has now fixed it. Thanks you!

joseph.olstad’s picture

@mkalkbrenner , it would really help us all if you could please tag and release.

bramvandenbulcke’s picture

A follow up from my side: I used patch 3379445-25.patch and thought everything was working fine but the count of the pager wasn't working with the patch installed. For example: select a facet selection with a result of 3 pages and when selecting the next page the pager goes to 9 pages.

As a temporary fix I disabled AJAX on these facet views.

joseph.olstad’s picture

ok, thanks for the followup @bramvandenbulcke
I postponed :
#3411788: Tag and release to fix - Facets breaks all AJAX views that uses pagers even without facets
Patch #25 and the pager, some remaining issue to work out.

soubi’s picture

With the patch #25 and views_infinite_scroll installed, I had to make my own url_processor plugin QueryString because the Request object used in the initializeActiveFilters function doesn't have any usable data to get the active filters when Ajax is enabled.

    if ($this->request->isXmlHttpRequest()) {
      $url_parameters = $this->request->request;
    }
    else {
      $url_parameters = $this->request->query;
    }

$url_parameters was always empty.

I replace it with

    if ($this->request->isXmlHttpRequest()) {
      $url_parameters = new InputBag($_GET);
    }
    else {
      $url_parameters = $this->request->query;
    }

in my custom url_processor plugin.

graber’s picture

This is not released yet? Seriously?
No further comments.

bramdriesen’s picture

Facets 3.0 is undergoing a major overhaul. What @StryKaizer is working on is not yet releasable.

chakkche’s picture

+1 for #35.

Filters are not being respected with latest dev or patch from #25. I have to overwrite initializeActiveFilters in my custom url proccessor. i have made similar change mentioned in #35

alban_g’s picture

I'm currently using version 3.0.0-beta1 and encountered an issue with broken AJAX pagination.
Applying Patch #25 resolved the problem.
Thank you for this patch!

tyler.hastain’s picture

I'm also currently using version 3.0.0-beta1 and was having the broken pagination issue when AJAX was turned on.
Applying Patch #25 resolved the problem for me as well.

paulrad’s picture

StatusFileSize
new18.12 KB

Here's the patch #25 with the Facets plugin still available for the Better Exposed Filters.
Version - 3.0.0-beta1

joseph.olstad’s picture

3.0.0-beta1 is far behind

I recommend someone tag 3.0.0-beta2 off of 3.0.x-dev

liquidcms’s picture

To fix facets break ajax paging (since upgrading core from 10.0 to 10.2); i upgraded Facets fro 3.0.0-beta1 to today's 3.0-dev.

Had to remove patch from here: #3172373: Disable updating the facets after each facet selection for Apply/Reset facet buttons block. as it no longer applies. Dev release does fix the issue with ajax paging however i no longer have a Views facet plugin. All views which had facet filters now show broken/missing handler.

I'll try going back to -beta1 and just using latest patch from here.

liquidcms’s picture

Patch from #41 on -beta1 rather than latest -dev fixes pager as well as facet exposed filters. Still doesn't apply with #3172373: Disable updating the facets after each facet selection for Apply/Reset facet buttons block. but i'll redo that patch.

jiong_ye’s picture

StatusFileSize
new17.26 KB

#41 works perfectly except it breaks empty facet get hidden behavior.

akshayadimolam’s picture

Patch #45 works for me on facets 3.0.0-beta1 on Drupal 10.3.6 & PHP 8.3. Pagination is working on all views.

kevinquillen’s picture

Patch no longer applies, the issue is marked fixed but is this really fixed in 3.x?

strykaizer’s picture

Facets + Blocks is not supported in Facets 3, and no patches for it will be accepted in Facets 3.
Blocks are still supported, but without ajax.

In Facets 3, use "Facets exposed filters" which has 100% ajax support, or stay on Facets 2 if you want blocks + ajax support.

"Facets exposed filters" focusses on the actual Facets parts (the filter itself), while offloading url-generation, widget generation, form placement etc. to views. One of the many advantages for this is 100% ajax support.

Facets 2 on the other hand had a lot of AJAX related issues, since the Facets module was handling all things mentioned above in its own way.

ressa’s picture

Thanks for clarifying that @strykaizer. It looks like currently, if you need AJAX support, only the default placement of facet filters above the View form is supported, since the https://www.drupal.org/project/configurable_views_filter_block does not yet support AJAX (#3374162: Make it work with AJAX enabled).

tondeuse’s picture

I have managed to produce a custom exposed filters display using Facets 3 and the Facets exposed filters with Ajax enabled. Using this strategy, a views infinite scroll pager is also functional. Locally, and from an insecure http:// request on a hosted site instance, ajax works, but changing exposed filters fails to return any results and wipes the facets filters clean when the request is made on a hosted instance behind nginx from and https:// URL.

I figure the solution lies in an AJAX alteration hook of the kind proposed by Karim in this post, but I am not sure how to alter the URLs exactly to workaround this SSL issue :
https://blog.karimratib.me/2025/05/21/drupal-ajax-views-exposed-filters....

The basic recipe I have used to produce a template for the exposed filters is this one, the view template itself does not have to be altered with twig, only the custom exposed filter template needs to be declared in a module with a theme hook :
https://makedrupaleasy.com/articles/drupal-10-make-beautiful-views-expos...

Any cues on how to work around this issue are welcome.

My exposed filters template :

<div class="row filters-wrapper">
  <div class="col-12 col-md-6 search-field-wrapper">
    <div class="form-group-search" id="full-text-search">
      {{ form.txt }}
      <div class="form-actions">
        {{ form.actions['submit'] }}
      </div>
    </div>
  </div>
  <div class="col-12 col-md-6 type-field-wrapper">
    <div class="form-group-select">
      {{ form.type }}
    </div>
  </div>
</div>