I have an interesting issue that I am trying to solve. Basically I need a page where users can search via textbox, and have select boxes to filter results on taxonomy terms.

I am using search_api_solr and built a view (as a page) based on my index. In my view, I created an exposed filter on the full text search. Also, I've created 2 facets, both on taxonomy term names. I've added the blocks to the page and everything looks good. When I search, the page refreshes and the facets are updated correctly.

The problem Im having is that I need the view to use AJAX so the results get updated without a page reload. I set the view to use ajax and saved it. Then when I go to my search page and enter in a search term, the search results get updated, but the facet blocks stay the same.

I tried to embed the facet blocks directly into view header, but they disappear when I enter a search term.

How can I get the facet blocks to work in views with AJAX enabled?

CommentFileSizeAuthor
#181 2826449-181.patch38.6 KBborisson_
#180 2826449.patch17.77 KBborisson_
#179 2826449-179.patch38.4 KBborisson_
#178 2826449-178.patch38.4 KBborisson_
#177 2826449-177.patch38.36 KBborisson_
#176 2826449-176.patch38.34 KBborisson_
#175 2826449-175.patch38.34 KBborisson_
#175 interdiff-2826449.txt636 bytesborisson_
#173 2826449-173.patch38.33 KBborisson_
#173 interdiff-2826449.txt827 bytesborisson_
#172 2826449-172.patch38.13 KBborisson_
#172 interdiff-2826449.txt4.39 KBborisson_
#171 2826449-171.patch36.6 KBborisson_
#171 interdiff-2826449.txt5.76 KBborisson_
#169 interdiff-2826449.txt18.22 KBborisson_
#169 2826449-169.patch35.26 KBborisson_
#166 ajax_facets-2826449-166.patch11.17 KBuzlov
#161 ajax_facets-2826449-161.patch24.65 KBtomasbarej
#157 interdiff.txt935 bytesStryKaizer
#157 ajax_facets-2826449-157.patch24.58 KBStryKaizer
#155 ajax_facets-2826449-155.patch24.47 KBmeanderix
#148 2826449-diff-146-148.txt1.19 KBflocondetoile
#148 2826449-148.patch19.78 KBflocondetoile
#146 interdiff.txt639 bytespiyuesh23
#146 facets-views-ajax-2826449-8.x-alpha11-146.patch19.53 KBpiyuesh23
#145 facets-views-ajax-2826449-8.x-alpha11-145.patch19.26 KBpiyuesh23
#144 interdiff-123_144.txt676 bytespiyuesh23
#144 facets-views-ajax-2826449-8.x-alpha11-144.patch19.26 KBpiyuesh23
#140 ajax_facets-2826449-140.patch24.46 KBRumyanaRuseva
#140 interdiff_138-140.txt3.3 KBRumyanaRuseva
#138 interdiff_2826449-138.txt1.27 KBMaico de Jong
#138 ajax_facets-2826499-138.patch24.1 KBMaico de Jong
#133 interdiff-2826449-128-133.txt478 bytesRumyanaRuseva
#133 ajax_facets-2826449-133.patch24.03 KBRumyanaRuseva
#128 interdiff.txt1.91 KBpiyuesh23
#128 ajax_facets-2826449-128.patch24 KBpiyuesh23
#126 interdiff_108-126.txt2.43 KBpiyuesh23
#126 ajax_facets-2826449-126.patch23.99 KBpiyuesh23
#123 interdiff-120_123.txt1.5 KBpiyuesh23
#123 facets-views-ajax-2826449-8.x-alpha11-123.patch19.23 KBpiyuesh23
#121 interdiff-57_120.txt1.93 KBpiyuesh23
#121 facets-views-ajax-2826449-8.x-alpha11-120.patch19.09 KBpiyuesh23
#120 interdiff-57_119.txt1.69 KBpiyuesh23
#120 facets-views-ajax-2826449-8.x-alpha11-119.patch19.22 KBpiyuesh23
#117 interdiff-2826449-108-117.txt584 bytesYurkinPark
#117 ajax_facets-2826449-117.patch24.38 KBYurkinPark
#108 interdiff-2826449-106-108.txt1.59 KBRumyanaRuseva
#108 ajax_facets-2826449-108.patch24.27 KBRumyanaRuseva
#107 ajax_facets-12455281-107.patch24.27 KBRumyanaRuseva
#107 interdiff-2826449-106-107.txt1.59 KBRumyanaRuseva
#74 2826449-74-ajax-facets.patch24.01 KBdiegodalr3
#74 interdiff-2826449-70-74.txt1.61 KBdiegodalr3
#5 facets-views-ajax-2826449-5.patch6.91 KBvasike
#9 facets-views-ajax-2826449-9.patch6.94 KBtomasbarej
#11 facets-views-ajax-2826449-11.patch6.98 KBtomasbarej
#14 facets-views-ajax-2826449-14.patch12.57 KBvasike
#21 facets-views-ajax-2826449-8.x-alpha9-21.patch13.85 KBpiyuesh23
#23 facets-views-ajax-2826449-8.x-alpha9-23.patch16.66 KBpiyuesh23
#23 interdiff.txt7.32 KBpiyuesh23
#24 facets-views-ajax-2826449-8.x-alpha9-24.patch18.58 KBpiyuesh23
#24 interdiff.txt6.42 KBpiyuesh23
#26 facets-views-ajax-2826449-8.x-alpha9-26.patch18.63 KBpiyuesh23
#26 interdiff.txt1.74 KBpiyuesh23
#30 2820347-views-block-exposed-filter-ajax-30.patch20.19 KBacbramley
#30 interdiff-26-30.txt5.36 KBacbramley
#34 facets-views-ajax-2826449-8.x-alpha9-34.patch19.43 KBpiyuesh23
#34 interdiff-26-34.txt2.8 KBpiyuesh23
#36 facets-views-ajax-2826449-8.x-alpha9-36.patch19.54 KBpiyuesh23
#36 interdiff.txt1.47 KBpiyuesh23
#37 facets-views-ajax-2826449-8.x-alpha9-37.patch19.53 KBpiyuesh23
#37 interdiff.txt735 bytespiyuesh23
#39 facets-views-ajax-2826449-8.x-alpha9-39.patch19.75 KBpiyuesh23
#39 interdiff.txt3.79 KBpiyuesh23
#41 facets-views-ajax-2826449-8.x-alpha9-41.patch19.7 KBpiyuesh23
#41 interdiff.txt3.74 KBpiyuesh23
#43 facets-views-ajax-2826449-8.x-alpha9-42.patch19.7 KBpiyuesh23
#43 interdiff.txt3.68 KBpiyuesh23
#44 facets-views-ajax-2826449-8.x-alpha9-43.patch19.81 KBpiyuesh23
#45 facets-views-ajax-2826449-8.x-alpha11-44.patch7.95 KBabhishek-anand
#46 facets-views-ajax-2826449-8.x-alpha11-46.patch14.75 KBrecrit
#46 interdiff-2826449-8.x-alpha11-44-46.txt6.81 KBrecrit
#47 facets-views-ajax-2826449-8.x-alpha11-47.patch19.6 KBrecrit
#47 interdiff-2826449-8.x-alpha11-46-47.txt4.85 KBrecrit
#51 2826449-interdiff.txt11.99 KBandypost
#53 2826449-interdiff-53.txt2.17 KBandypost
#53 2826449-ajax-facets-53.patch18.85 KBandypost
#57 facets-views-ajax-2826449-8.x-alpha11-57.patch19.7 KBnikunjkotecha
#57 interdiff-47-57.txt1.35 KBnikunjkotecha
#58 facets-views-ajax-2826449-8.x-alpha11-58.patch19.93 KBniknak
#60 facets-views-ajax-2826449-8.x-1.0-alpha11-60.patch19.36 KBdenis_kv
#64 facets-views_ajax-2826449-64.patch41.37 KBacrollet
#66 2826449-ajax-facets-66.patch19.97 KBandypost
#70 interdiff.txt11.19 KBMaico de Jong
#70 2826449-ajax-facets-70.patch23.69 KBMaico de Jong
#77 interdiff-286449-74-77.patch539 bytesniknak
#79 2826449-ajax-facets-79.patch23.96 KBniknak
#79 facets-ajax-interdiff-74-79.txt630 bytesniknak
#83 interdiff-2826449.txt11.16 KBborisson_
#83 ajax_facets_blocks_for-2826449-83.patch22.3 KBborisson_
#85 ajax_facets_blocks_for-2826449-85.patch22.79 KBcato
#85 facets_ajax_interdiff-83-85.txt410 bytescato
#99 ajax_facets_blocks_for_views-2826449-99.patch23.37 KBgaydabura
#99 interdiff-2826449-85-99.txt3.27 KBgaydabura
#100 ajax_facets_blocks_for_views-2826449-100.patch23.37 KBgaydabura
#100 interdiff-2826449-85-100.txt3.19 KBgaydabura
#102 ajax_facets_blocks_for_views-2826449-102.patch23.86 KBgaydabura
#102 interdiff-2826449-85-102.txt5.83 KBgaydabura
#104 ajax_facets_blocks_for_views-12455281-104.patch23.75 KBfinnsky
#104 interdiff-2826449-12455281-104.txt676 bytesfinnsky
#106 interdiff-partial-2826449-104-106.txt2.87 KBRumyanaRuseva
#106 interdiff-2826449-104-106.txt7.46 KBRumyanaRuseva
#106 ajax_facets-2826449-106.patch24.25 KBRumyanaRuseva
#51 2826449-ajax-facets-51.patch18.83 KBandypost
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sagesolutions created an issue. See original summary.

borisson_’s picture

We currently don't have any specific integration for that yet. So currently I don't think there's a way to do this out of the box.

jummonk’s picture

First of all, I'd like to mention that your work on facets is awesome borisson. (We met at DrupalCamp Ghent a few months ago.)

I'm currently working on a project about to go live (soft launch) in a month or so. My customer would love to have this ajax behaviour on their search results pages. The site is actually totally search driven.

I have some questions:

  • Is there a roadmap for facets I can check out?
  • Is there a way to get this ajax behaviour on the roadmap?
  • Might a custom implementation of this conflict with future updates of the facets module?

Thanks in advance for any feedback.

borisson_’s picture

Is there a roadmap for facets I can check out?

Not really. The "roadmap" I have is mainly in my head. Important issues are tagged with beta blocker. https://www.drupal.org/project/issues/search/facets?project_issue_follow... We closed 5 beta blockers this week and currently have only one remaining.
The priority for me is:
- Fixing tests so that they pass on https://travis-ci.org/mkalkbrenner/search_api_integration_tests
- #2831436: Add dependency information to display plugins
- #2772745: Search API integration doesn't check/define feature support of backends
Release a beta
- Clean up the integration with search api pages + add tests for that.
- Fix other open issues in the queue.

Is there a way to get this ajax behaviour on the roadmap?

- I guess providing a patch with tests is the best way ;) Before starting on a patch however - there should be a clear direction on how to achieve the functionality.
The clearest path towards getting ajax behavior in is by helping us figure out a way on how to implement it in this issue.

Might a custom implementation of this conflict with future updates of the facets module?

- It might, it might not. I guess it depends on the way it is implemented.

vasike’s picture

Version: 8.x-1.0-alpha6 » 8.x-1.x-dev
Status: Active » Needs review
FileSize
6.91 KB

here is patch as an approach proposal for this features

This approach it's something i found in other contrib Facets module : Core Views Facets

So what's there:

  • It adds new helper method for Facets Source plugin that could add some specific elements to the FacetBlock plugin
  • Update Search API facet source plugin and implement this new method and add specific js if the facet source is for a View with Ajax enabled (code inspired from Core Views Facets module)
  • And ofcourse the JS file which also is from Core Views Facets module.

ToDo:
The patch here update the View but not the facets.
In D7 we have block for all facets, but in D8 we have a block for every facet.
So we need to build an Ajax system similar with what's for Views for FacetBlocks.
And ajaxresponse for FacetBlocks and also a identifying system to the current (present) facets that needs to be reloaded.

imho, this block ajax system sound more generic than only for Facets module, but i don't think this is something we could bring into Drupal core.

Personally i'm not that good with js and ajax, so any help here, including suggestions, is welcome.

Of course this just a proposal, maybe there are better solution for this.

p.s.: i selected "Needs review", as i think we need at least some reviews from others about this approach/patch.

vasike’s picture

i also (just) found this blog post related
http://cclub.cf/article/ajax-facets-drupal-8

Maybe it helps here

borisson_’s picture

Thanks for providing the patch here @vasike. I'm not sure how to feel about this yet. I'm going to try to come back to this issue soon.

acbramley’s picture

Definitely interested in this feature, we will need 2 way binding between the facets and the view. I.e if the view is filtered via exposed filters with ajax, the facets will need to update and if the facets are used the view needs to update.

tomasbarej’s picture

I had to change facets-views-ajax.js file in vasike patch. Otherwise the patch works so triggering facet correctly reloads view.

Status: Needs review » Needs work

The last submitted patch, 9: facets-views-ajax-2826449-9.patch, failed testing.

tomasbarej’s picture

acbramley’s picture

Status: Needs work » Needs review

Retrigger tests

acbramley’s picture

+++ b/js/facets-views-ajax.js
@@ -0,0 +1,62 @@
+          var view = $('.view-id-' + facetSettings.view_id + '.view-display-id-' + facetSettings.current_display_id).first();
+
+          var start = view.attr('class').indexOf('js-view-dom-id-');
+          var end = view.attr('class').indexOf(' ', start);
+          var current_dom_id = view.attr('class').substr(start + 15, (view.attr('class').length - start - 15 - (view.attr('class').length - end)));

This fails if the view doesn't have the correct classes. We need a safer way to check. Potentially iterating over the Drupal.views.instances instead?

vasike’s picture

And there is a new patch, continuing the previous patches

Updates:
- First, fix the #13 - fails the get the view
- Implement an AJAX Facets Blocks reload/refresh (new ajax route + new ajax controller + extra js).

I think the code could be improved, so please try and review it.
Thank you

acbramley’s picture

+++ b/js/facets-views-ajax.js
@@ -0,0 +1,85 @@
+        var view = $('.view-id-' + facetSettings.view_id + '.view-display-id-' + facetSettings.current_display_id).first();

My problem with the classes actually came from this line here (sorry if that was confusing in #13). I'm not sure if our setup is removing these classes or yours is adding them?

vasike’s picture

@acbramley
- for #13 indeed it was an issue with getting the view element.
- #for #15, it looks like you have some other classes: could we share the view div (element you have) or at least the classes for it.

Btw, is your other View ajax works?

acbramley’s picture

@vasike my view div looks like:

<div class="contextual-region js-view-dom-id-e60c446ecc6fe5614c5e23591c451cedf1efb6e951ebf52577d089620b6b7120">

Other views AJAX functionality does work, I can expose sorts via AJAX and use them fine.

I have a custom template for this view, but it is almost identical to the stable theme's views-view.twig.html and I have no preprocessing on it at all.

vasike’s picture

@acbramley unfortunately the View dom-id is not available at the moment the facets are build so we use the view id and display id
to identify the View wrapper.

but feel free to come with a new patch that fix this.

acbramley’s picture

@vasike yeah that makes sense, it looks like the classy theme adds those classes to the view. I will test adding those classes to our template and retest the patch although we would need to figure out how we can get around requiring them in the JS implementation since it will confuse others who don't use the classy base theme as well.

acbramley’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

I've had a more in depth test with #14 and these are my findings:

  1. +++ b/js/facets-views-ajax.js
    @@ -0,0 +1,85 @@
    +        var current_dom_id = $.map(view.attr('class').split(' '), function (v, i) {
    +          if (v.indexOf(dom_id_start) > -1) {
    +            return v.slice(dom_id_start.length, v.length);
    +          }
    +        });
    

    Need to add a .join() here since .map() returns an array.

  2. +++ b/js/facets-views-ajax.js
    @@ -0,0 +1,85 @@
    +        $('ul[data-drupal-facet-id=' + facetId + ']  li').once().click(function (e) {
    

    This is limiting anyone retemplating facets, for example we used fieldset elements with divs. the ul restriction can be removed along with the li and use .children() instead.

  3. +++ b/src/Controller/FacetBlockAjaxController.php
    @@ -0,0 +1,128 @@
    +  /**
    +   * Constructs a FacetBlockAjaxController object.
    +   *
    +   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
    +   *   The container.
    +   */
    +  public function __construct(ContainerInterface $container) {
    +    $this->container = $container;
    +    $this->storage = $container->get('entity.manager')->getStorage('block');
    +    $this->renderer = $container->get('renderer');
    +    $this->currentPath = $container->get('path.current');
    +    $this->router = $container->get('router');
    +    $this->pathProcessor = $container->get('path_processor_manager');
    +  }
    +
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public static function create(ContainerInterface $container) {
    +    return new static(
    +      $container
    +    );
    +  }
    

    You should be injecting each service separately rather than the entire container.

  4. +++ b/src/Controller/FacetBlockAjaxController.php
    @@ -0,0 +1,128 @@
    +      $block_entity = $this->storage->load($facets_block);
    +      $block_view = \Drupal::entityTypeManager()
    +        ->getViewBuilder('block')
    +        ->view($block_entity);
    

    This only works under very specific circumstances. For example we are using DS fields to render facet blocks via a node display for some search pages, and panels blocks for another. I've looked at how DS's BlockBase does this and it uses
    a block plugin manager to create the block instance and render it, which seems to work for the most part:

    $block_manager = $this->container->get('plugin.manager.block');
    foreach ($facets_blocks as $facets_block) {
      $block_id = 'facet_block:' . $facets_block;
      $block = $block_manager->createInstance($block_id);
    
      $block_view = $block->build();
      $response->addCommand(new ReplaceCommand('.js-facet-dom-id-' . $facets_block, $block_view));
    }
    

    The problem with that is it loses the context of how it was originally rendered. For the DS Field example we have to use field preprocessing to pass along the facet block classes to the field template but it then loses that after the first AJAX request.

I'm going to continue looking into how we can re-render the block as it was originally rendered next.

piyuesh23’s picture

Status: Needs work » Needs review
FileSize
13.85 KB

Hi acbramley,

We are working on a Drupal site needing this feature as well. Have ported the patch for the latest recommended release 8.x-1.0-alpha9. Adding this patch here for anyone else using the same version. Also, your review points #1,#2, #3 make complete sense to me & are incorporated in the patch being attached here. With #4, somehow i am loosing the layout around my facet blocks using the default block layout.

Another important addition to this patch is making sure the cache context around urls work correctly. Have appended the filter query to view_settings object's url to leverage url context.

acbramley’s picture

@piyuesh23 great to see you're working on it! Would you be able to please post an interdiff between your patch and #14? I did find the same thing as what you describe in #4 but I didn't get a chance to figure out how to get around it properly.

piyuesh23’s picture

Added support for AJAXifying facet summary block as well. Attaching patch & interdiff. Please note this patch is against 8.x1.0-alpha9 release. Will soon port it to dev & attach a patch here.

piyuesh23’s picture

Generalizing the solution a bit more by exposing facet summary block ids. Also, fixed another bug where facets don't preserve the URL correctly with view blocks. Attaching the patch here.

sylus’s picture

This is great and the latest patch works great for me with facets and facet summary. The only issue I have is while I click the facet the view does update, the facet that was clicked doesn't add a checkbox to the item and remains unchecked.

piyuesh23’s picture

@sylus,

Thanks for testing the patch & your feedback. The patch works well for me & updates the facet checkboxes as well. Are you sure you haven't taken off any class attached with the facets by default?

In the meanwhile, i ran into another case where the facet settings to not render a facet block without items was not being honored. Attaching patch with the fix around the same.

sylus’s picture

I think my problem might be I am rendering the facets via panelizer / panels depending on the use case and not relying on the standard block interface?

acbramley’s picture

@sylus yeah this patch is specifically targeting normal blocks configured via the block interface (see the following code which loads the block)

+++ b/src/Controller/FacetBlockAjaxController.php
@@ -0,0 +1,177 @@
+        $block_entity = $this->storage->load($facet_summary_block_id);
+        $block_view = $this->entityManager->getViewBuilder('block')
+          ->view($block_entity);

As explained in #20 we need a way for this to work consistently across all methods of displaying blocks. For example I'm using a block field to render them.

sylus’s picture

Yup that was indeed the problem, thank you so much!

I took a look at your mentioned workaround and it did indeed make my first facet show up with the checkbox, with the aforementioned styling issue on a panelizer page. So agreed definitely going to be find a consistent way to do this. ^_^

Thanks for the clarification :)

acbramley’s picture

Here's a patch that changes to using the plugin manager to render the blocks. I'm having a small issue where every ajax request adds a wrapper div but checking and unchecking checkboxes is now working.

With #26 the ajax classes weren't being added to the new block, moving the classes to a preprocessor has fixed that.

Still need tests and a lot of refactoring to inject the new services that are being used.

Status: Needs review » Needs work

The last submitted patch, 30: 2820347-views-block-exposed-filter-ajax-30.patch, failed testing. View results

acbramley’s picture

Another issue I'm seeing is if there are 2 facet blocks on the page, and using one removes the results from the other, the block is not removed when either is used.

sylus’s picture

The latest patched worked great for me! Thanks for the great work!

There was two issues I noticed:

a) The block doesn't get rendered with the title
b) If you have a facet with a soft limit of 25, on ajax the full list will instead be inserted

For the title issue I made the following adjustments:

    $block = $this->blockManager->createInstance($block_plugin_id);
    if ($block) {
      $block_build = $block->build();
      $block_configuration = $block->getConfiguration();
      $block_configuration['label'] = $block->label();
      if (!empty($block_build)) {
        $return = [
          '#theme' => 'block',
          '#attributes' => [],
          '#configuration' => $block_configuration,
piyuesh23’s picture

@acbramley,

Tried your patch locally. But, i get a missing block error for my facet summary block trying to build one. In the meanwhile, the div wrapper around the facets post AJAX is a known core issue https://www.drupal.org/node/736066 being worked upon for 8.4.x.

For now, attaching a workaround here using Invoke Command & JS function to handle the same. Attaching patch & interdiff from #26 here.

acbramley’s picture

+++ b/src/Controller/FacetBlockAjaxController.php
@@ -0,0 +1,191 @@
+        $block_view = $block_view->__toString();
+        ¶

You should use (string) casting rather than calling the function directly. Also looks like you've got some trailing whitespace here

piyuesh23’s picture

@acbramley, Thanks for the review. Not sure if type-casting to string would return the same thing. block_view is an instance of Markup class for facets & string for facet summary.

Adding a check here to resolve errors & removing the trailing whitestpace.

piyuesh23’s picture

Also, noticed that since we replaced the call to ReplaceCommand with InvokeCommand & using a custom JS function, Facet summary filters stopped working on AJAX. Removing context check from the selector since we are replacing content inside this wrapper & context would not have the wrapper div.

borisson_’s picture

Status: Needs work » Needs review

@acbramley, Thanks for the review. Not sure if type-casting to string would return the same thing. block_view is an instance of Markup class for facets & string for facet summary.

(string) $object is the same thing as $object->__toString();. So that is the same thing. So let's remove those instanceof calls.

I haven't looked at the complete patch yet, my feelings on this issue haven't changed since #7, not sure if this approach is the best and if we even should include this in the main module.

I see that there's a getView method in here, let's remove that and get some feedback on #2860393: API break: Add getViewsDisplay method to the Search API Facet Source instead.

This will need tests, at the very least a javascriptTest to ensure that this actually fixes this.

piyuesh23’s picture

@borisson, Thanks for the review. Updating my patch with typecasting. Also, noticed the active state for the facets get lost post ajax. Maintaining that back in this new patch.

piyuesh23’s picture

Please ignore the previous patch. Something i was trying while debugging this with my project, got pushed in as well. Will push off a sanitized version soon.

piyuesh23’s picture

Uploading an updated patch here.

Status: Needs review » Needs work

The last submitted patch, 41: facets-views-ajax-2826449-8.x-alpha9-41.patch, failed testing. View results

piyuesh23’s picture

FileSize
19.7 KB
3.68 KB

Previous patch doesn't apply for some reason. Re-rolling & pushing an updated one.

piyuesh23’s picture

Another issue:
Apply a facet which hides one of the facet filters. Try clearing that facet on AJAX. Ideally, the previous facet should appear back. It doesn't appear back, since the DOM-id for the facet filter gets lost.

Uploading patch to handle this case.

abhishek-anand’s picture

Updated patch suitable for alpha11 release.

recrit’s picture

The last patch was missing the new file for the FacetBlockAjaxController. The patch attached adds that file back.

recrit’s picture

#43 was missing facets-views-ajax.js also. The attached patch adds that file back.

ac’s picture

#47 applies and works for the most part, although I found one problem:

Usage: Output a facet as a list of links that then filter a list of products (basically this but using links instead of checkboxes: http://docs.drupalcommerce.org/v2/product/create-a-product-catalog.html). 'Ensure that only one result can be displayed' is checked for the facet.

Issue: If you select a link it works but if you then select another link from the same facet it reverts to using URL queries (works fine if you select a link from a different facet).

borisson_’s picture

So, I'm still not 100% sure if we should do this, but if this needs to move to a seperate module, we'd need to at least get the api in here. I also had some nits to pick on the code.

  1. +++ b/facets.libraries.yml
    @@ -53,3 +53,12 @@ soft-limit:
    +    - core/drupal.ajax
    \ No newline at end of file
    

    Needs newline.

  2. +++ b/facets.routing.yml
    @@ -48,3 +48,9 @@ entity.facets_facet_source.edit_form:
    +    _access: 'TRUE'
    \ No newline at end of file
    

    Needs newline.

  3. +++ b/src/Controller/FacetBlockAjaxController.php
    @@ -0,0 +1,193 @@
    +   * @param \Drupal\Core\Entity\EntityManager $entityManager
    +   * @param \Drupal\Core\Render\RendererInterface $renderer
    +   * @param \Drupal\Core\Path\CurrentPathStack $currentPath
    +   * @param \Symfony\Component\Routing\RouterInterface $router
    +   * @param \Drupal\Core\PathProcessor\PathProcessorManager $pathProcessor
    +   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger
    +   */
    

    These need a description.

  4. +++ b/src/Controller/FacetBlockAjaxController.php
    @@ -0,0 +1,193 @@
    +  public function __construct(EntityManager $entityManager, RendererInterface $renderer,
    +                              CurrentPathStack $currentPath,
    +                              RouterInterface $router,
    +                              PathProcessorManager $pathProcessor,
    +                              LoggerChannelFactoryInterface $logger) {
    

    I don't think there are any places where we do this, we always just let this flow to one line.

  5. +++ b/src/Controller/FacetBlockAjaxController.php
    @@ -0,0 +1,193 @@
    +      throw new NotFoundHttpException();
    ...
    +      throw new NotFoundHttpException();
    

    Let's give these messages, so it's clearer why things fail.

  6. +++ b/src/Controller/FacetBlockAjaxController.php
    @@ -0,0 +1,193 @@
    +        // @Todo: Replace with ReplaceCommand once https://www.drupal.org/node/736066 gets fixed.
    

    80 cols.

  7. +++ b/src/Controller/FacetBlockAjaxController.php
    @@ -0,0 +1,193 @@
    +    if ($update_summary_block) {
    

    Let's switch this if to reduce indentation. if (!$update_summary_block) { return $response }

  8. +++ b/src/Plugin/facets/facet_source/SearchApiDisplay.php
    @@ -326,4 +326,44 @@ class SearchApiDisplay extends FacetSourcePluginBase implements SearchApiFacetSo
    +  public function getView() {
    

    We also added this in #2860393: API break: Add getViewsDisplay method to the Search API Facet Source, can anyone review / rtbc that issue so we can use that implementation here (which is a little bit more defensive)?

Flodevelop’s picture

Thank you for this patch, seems to works nicely.

Just a remark, when you apply the patch #47, files FacetBlockAjaxController.php and facets-views-ajax.js can be misplaced out of the module facets folder, then logically show this error :
ReflectionException: Class \Drupal\facets\Controller\FacetBlockAjaxController does not exist in ReflectionMethod->__construct() (line 123 of core/lib/Drupal/Core/Entity/EntityResolverManager.php).

andypost’s picture

That still needs tests and more clean-up, I see no reason to extract it to separate module cos the change is not so big but external module will need a lot of hacks to override facet plugins & other internals ( ref https://github.com/waspper/ajax_facets

Patch fixes #49 1-4, 6,8
5 - not sure we need to report which keys missing in request, and probably we need to add access checker for the route
7 - I cleaned a bit but early return at the end of logic makes no sense

#50 that's does not related to patch, just use proper tool to apply

Status: Needs review » Needs work

The last submitted patch, 51: 2826449-ajax-facets-51.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

andypost’s picture

Status: Needs work » Needs review
FileSize
2.17 KB
18.85 KB

Fix broken tests & coding standards

Status: Needs review » Needs work

The last submitted patch, 53: 2826449-ajax-facets-53.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Kristen Pol’s picture

I tried #53 with the dev version but had no luck. Have a facet with checkboxes. When I click a checkbox, I get:

base.js?v=8.3.6:26 Uncaught TypeError: Cannot read property 'indexOf' of undefined
    at Object.Drupal.Views.parseQueryString (base.js?v=8.3.6:26)
    at updateFacetsView (facets-views-ajax.js?ovfmj4:77)
    at HTMLLIElement.<anonymous> (facets-views-ajax.js?ovfmj4:68)
    at HTMLLIElement.dispatch (jquery.min.js?v=2.2.4:3)
    at HTMLLIElement.r.handle (jquery.min.js?v=2.2.4:3)

Anyone had success with the patch?

andypost’s picture

@Kristen Pol - good catch, I did not used checkboxes

nikunjkotecha’s picture

Bit of performance enhancement.

niknak’s picture

I found some mistake for checkbox widget and hierarchical link in facet with ajax, inside js file.

In patch #57, the selector match for first element in hierarchical links, if clicked in depth link, always first link with 'facet-item' class is selected.

For the checkbox widget, on event listener "change", we use "window.location.href". For me, it does not work, this reload the page, i change this line by a trigger function on click event the hidden link related on this checkbox.

nikunjkotecha’s picture

@niknak possible to share interdiff? points look interesting

denis_kv’s picture

Thanks for the patch. I found an issue with patch #58. When i tried to use widget "List of links" it had problems with links wrapped into

  • tag. This patch should solve the issue with "List of links".
  • borisson_’s picture

    Status: Needs work » Needs review

    Let's see how the testbot feels about #60

    The last submitted patch, 57: facets-views-ajax-2826449-8.x-alpha11-57.patch, failed testing. View results

    Status: Needs review » Needs work

    The last submitted patch, 60: facets-views-ajax-2826449-8.x-1.0-alpha11-60.patch, failed testing. View results

    acrollet’s picture

    Status: Needs work » Needs review
    FileSize
    41.37 KB

    re-rolled against HEAD

    Status: Needs review » Needs work

    The last submitted patch, 64: facets-views_ajax-2826449-64.patch, failed testing. View results
    - codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

    andypost’s picture

    sylus’s picture

    Could anyone give this a try on a panelizer page, with a list of checkboxes for each facet. Unfortunately this logic doesn't work for this use case.

    Status: Needs review » Needs work

    The last submitted patch, 66: 2826449-ajax-facets-66.patch, failed testing. View results
    - codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

    Maico de Jong’s picture

    Great work! I tried patch #66 on a SOLR search view with multiple facets, all using the 'list of links' widget, using the core block system. Basics are working fine, although i ran into some errors/bugs:
    - Block id's are not always correct, i manually changed the block id's of the facets when i added them to a region. I had to re-add these blocks with their default id's, then it started working
    - When facet blocks are replaced with ajax, all links loses their query paramaters for views exposed filters. (?search=&sort_by=)
    - When clicking on another facet link, before the ajax call is finished, it keeps loading forever

    Maico de Jong’s picture

    FileSize
    23.69 KB
    11.19 KB

    Updated patch #66 with some new features, including two way refresh, so facets blocks are updated on views exposed filter change.

    Use block id for loading and replacing facet blocks
    There was no way to really know the block id if you change the default or have duplicate blocks on one page. Block ids are now stored in block configuration on block form submit and in hook_update()

    Rewrite JS file
    Facet blocks and view can be updated separately now

    Use history.pushState()
    Not sure about this one, i could not find a simple way to generate the updated url with exposed information needed to regenerate the facet links. Therefore, i used history.pushState() to update the url on facet link click. Updating the url on exposed filter change is handled by the views_ajax_history module (1.x dev). Using both this patch and enable views_ajax_history works great in my case. Settings views_ajax_history as a dependency is not an option because it's only needed when Ajax is enabled and views_ajax_history is still in dev.

    This is probably not a final solution, but i hope it will help in creating a solid patch.

    acrollet’s picture

    Status: Needs work » Needs review

    triggering testbot.

    The last submitted patch, 70: 2826449-ajax-facets-70.patch, failed testing. View results
    - codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

    niknak’s picture

    I tried the last patch #70, it's work fine, but i found always same error with hierarchical facets.

    I think this line is the problem for hierarchical facets.
    $('[data-drupal-facet-id=' + facetId + ']').children('.facet-item').once().click(function (e) {

    The "children" selector with "once" function, match only first link not children, if click in a children link, then, the real click is on first link of hierarchical facet it unselect the parent

    diegodalr3’s picture

    Fix facets ajax with hierarchical facets and dropdown.

    The last submitted patch, 74: 2826449-74-ajax-facets.patch, failed testing. View results
    - codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

    sylus’s picture

    Thanks for the amazing work! It seems like the latest patch works on first click but I can't do any subsequent ones.

    niknak’s picture

    FileSize
    539 bytes

    With this diff, the patch work after first click.

    But in url, the parameters not adding with the existing facets, only one facet can be clicked.

    Status: Needs review » Needs work

    The last submitted patch, 77: interdiff-286449-74-77.patch, failed testing. View results

    niknak’s picture

    Well, I worked for this issue, and I found, maybe, the last bug.

    In the controller of ajax facet, inside "foreach", we load the block entity with the key of "foreach", in case block id contains a underscore, facets not found the block entity. I remove the comment "$facets_block_id = str_replace('_', '', $facets_block);" and used str_replace for block id (key of "foreach").

    I take the opportunity to add the last change #77

    I hope not see new errors

    acrollet’s picture

    Status: Needs work » Needs review

    triggering testbot

    Status: Needs review » Needs work

    The last submitted patch, 79: 2826449-ajax-facets-79.patch, failed testing. View results
    - codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

    sylus’s picture

    I tried the latest patch but it doesn't seem to work for some facet clicks, also once a facet does register as clicked can't seem to submit another one.

    borisson_’s picture

    Status: Needs work » Needs review
    FileSize
    11.16 KB
    22.3 KB

    So - my suggestion in #49.8 was not implemented, so I did that. I also fixed some coding standards things and made the controller extend the controllerbase class. Other cleanups as well.

    This still needs automated tests, and testfixes for the other tests.

    We've been wanting to tag a first beta release for a while, and this change is not bc compatible (because of the changes in src/FacetSource/FacetSourcePluginInterface.php.

    So if we want to get a stable release out, and that change is needed (and it looks like it is), we should really accelerate this.

    Status: Needs review » Needs work

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

    cato’s picture

    Tried the patch in #83 which worked for the first click on a facet but any following clicks resulted in an error 500 Call to a member function getViewBuilder() on null in modules/contrib/facets/src/Controller/FacetBlockAjaxController.php on line 140

    Changing $this->entityManager to $this->entityTypeManager seems to do the trick...

    niknak’s picture

    It would not miss parentheses? for "$this->entityManager or $this->entityTypeManager" ?

    cato’s picture

    @niknak Too me it looks like we're calling a method on entityTypeManager. The entityTypeManager class should be constructed already.

    cato’s picture

    There is another bug that I haven't tracked down yet that happens to me intermittently. The checkboxes turn into links sometimes, it would seem that the makeCheckboxes() js function doesn't always run.

    niknak’s picture

    @cato, For the checkboxes bug, i same probleme.

    I found another error, I have 5 facets and many links for each, if I click on one link, the JS call ajax for each link.

    I think this probleme is in facets-views-ajax.js at 59 lines "$(facet_item).children('a').click(function (e) {"
    But if add .once before "children", the ajax do not always work.

    Anyone to an idea?

    cato’s picture

    @niknak I spent last friday digging through it and didn't find what's causing the problems.. It seems that sometimes the link elements don't get replaced with the needed input type etc structure. Not sure why this happens.

    As to the problem in #89 - I've got five facets and from what I can see, each facet-item contains only one link. Also the function below should only bind each checkbox / link to a click method, not call .click on each element. So it's outside-in, not inside-out. If you're seeing that every link gets clicked when you check one checkbox / click on one link then I think something else is broken.

    $('[data-drupal-facet-id=' + facetId + ']').find('.facet-item').each(function (index, facet_item) {
    $(facet_item).children('a').click(function (e) {
    e.preventDefault();
    updateFacetsView($(this).attr('href'), current_dom_id);
    });
    });

    cato’s picture

    Sooo... @borisson_ is Ajax something that's on the roadmap for Facets in D8? I'm kinda stuck on getting this patch working completely and I fear my JS skills aren't quite what they need to be to fix it.

    borisson_’s picture

    I discussed this over the weekend with @StryKaizer. This is something that is on the roadmap!

    However, before we're willing to commit this, we should provide this with very extensive testcoverage.

    This because there are some issues in Drupal's ajax system. (like #736066: ajax.js insert command sometimes wraps content in a div, potentially producing invalid HTML and other bugs). We want to avoid getting issues about things like that in our queue, as well as it being a huge feature.

    Currently, we're trying to focus on getting bugfixes in and that way trying to get as close to a stable release as possibe, hopefully somewhere in the next couple of months.

    An issue that's as big as this will probably be something we pick up during a week-long sprint surrounding an event (possibly drupal dev days in july 2018), this is not something I'm willing to spend an entire weekend on, just like you - my JS-skills are also lacking and I'm afraid I won't be able to do much in a weekend.

    As a first step, we should try to write out tests (these can be just a comments in a new testmethod if needed) for all the behaviors that are expected and the edgecase encountered so far.

    acbramley’s picture

    +1 for the approach in #92!

    niknak’s picture

    @Cato, I investigated for my problem, on page load, if I have webform block displayed on this page, the Drupal.behaviors.facetsViewsAjax is called many time.

    If disable this webform, the Druapl.behoaviors.facetsViewsAjax is called just one time, in this case the context is just "document".

    I think, that there is a conflict with webform module

    niknak’s picture

    I come back to a problem that I had before.

    After clicking on one or more facets, the page is reloaded.

    After analyzing the problem, I'm thinking that we go back in the attach only to the return of the view but the ajax to update the facets comes after and overwrites the html and therefore the event clicks.

    I do not really know how attach for ajax returns.

    seanpclark’s picture

    @niknak for #89 I believe the issue you're describing would be resolved by using the context variable on line 58 of facets-views-ajax.js:

    $('[data-drupal-facet-id=' + facetId + ']', context).find('.facet-item').each(function (index, facet_item) {
    
    niknak’s picture

    @seanpclark, in theory it is a good solution, but the context on loading page is document object, and after ajax refresh, is views result list element.

    My problem for #89, its not really the facets issue, but drupal/webform issue. Only with admin user (when contextual link is enable) and a webform block display on this page.

    So after ajax refresh, sometimes after 3 or 4 refresh or less, and this is my problem for #95. Ajax-facets-js send two ajax call (for update views result list and update facets), the event click of facets link is attached before callback of second ajax call (update facets). therefore the event no longer exists.

    meanderix’s picture

    Has anyone attempted to use this with the Context module? ISTM that the Context module defines its own block storage and hence, the block look-up in FacetBlockAjaxController::ajaxFacetBlockView() will fail, i.e.:

     $block_entity = $this->storage->load($facets_block_id);
    

    In addition, FacetBlock::blockSubmit() throws an error due to $form['id'] being undefined.

    gaydabura’s picture

    FileSize
    23.37 KB
    3.27 KB

    Rerolled patch for latest dev

    gaydabura’s picture

    andypost’s picture

    1. +++ b/facets.install
      @@ -149,3 +150,20 @@ function facets_update_8005() {
      +function facets_update_8006() {
      +    $query = \Drupal::entityQuery('block')
      +        ->condition('plugin', 'facet_block', 'STARTS_WITH')
      +        ->execute();
      +
      +    foreach ($query as $block_id) {
      +        $block = Block::load($block_id);
      +        $configuration = $block->get('settings');
      +        $configuration['block_id'] = $block_id;
      +        $block->set('settings', $configuration);
      +        $block->save();
      +    }
      

      indent should be 2 spaces

    2. +++ b/js/checkbox-widget.js
      @@ -43,7 +43,7 @@
      -      window.location.href = $(this).data('facetsredir');
      +        $(this).siblings('a').trigger('click');
      

      wrong indent

    gaydabura’s picture

    Views ajax route name added, as we may have different url for language or even it can be altered in custom modules.

    andypost’s picture

    Managing entities in update hooks very bad ide, better use post update hook when kernel is consistent

    finnsky’s picture

    I catched issue when filters disappear after dropdown change. And found that class 'item-list__dropdown' not good for selector here. For example i had this class as 'item-list__country_widget'.
    'facets-dropdown' seems more logical as selector here. From js/dropdown-widget.js:37

          // Remove the class which we are using for .once().
          $dropdown.removeClass('js-facets-dropdown-links');
    
          $dropdown.addClass('facets-dropdown');
    

    Added small patch.

    andypost’s picture

    +++ b/js/facets-views-ajax.js
    @@ -64,8 +64,8 @@
    +            if ($(facet_item).hasClass('facets-dropdown')) {
    

    for such classes core using js- prefix see https://www.drupal.org/node/2452043

    RumyanaRuseva’s picture

    Here's an updated patch with some issues fixed:
    1. Added js- prefix on .js-facets-dropdown as noted by andypost.
    2. Added back .once() when assigning the click handler. It seems that it was accidentally removed in https://www.drupal.org/files/issues/interdiff-2826449-70-74.txt and it resulted in assigning the click handler multiple times, executing the ajax multiple times per click, and stuck loading animation.
    3. Fixed js error when settings.views.ajaxViews was missing.
    4. Fixed coding standard errors found by Code Sniffer.

    interdiff-partial contains the diff for 1-3, before the coding standard fixes.

    RumyanaRuseva’s picture

    The following error occurred on node save when Search API tried to push the updated content into the index:

    Error: Call to a member function getRouteParameters() on boolean in Drupal\facets\Widget\WidgetPluginBase->Drupal\facets\Widget\{closure}() (line 64 of .../modules/contrib/facets/src/Widget/WidgetPluginBase.php) 
    #0 [internal function]: Drupal\facets\Widget\WidgetPluginBase->Drupal\facets\Widget\{closure}(Object(Drupal\facets\Result\Result)) #1 .../modules/contrib/facets/src/Widget/WidgetPluginBase.php(72): array_map(Object(Closure), Array) 
    #2 .../modules/contrib/facets/src/Plugin/facets/widget/LinksWidget.php(37): Drupal\facets\Widget\WidgetPluginBase->build(Object(Drupal\facets\Entity\Facet)) 
    #3 .../modules/contrib/facets/src/Plugin/facets/widget/CheckboxWidget.php(22): Drupal\facets\Plugin\facets\widget\LinksWidget->build(Object(Drupal\facets\Entity\Facet)) 
    

    In my case there is a field "full rendered content" in the Solr search index.

    We should check the result of getUrlIfValid() before using it as Url object.
    Besides, $route_params and $route_name are not used unless $result->getUrl()->getRouteName() === 'facets.block.ajax', so there can be a single check for both.

    Here is a patch.

    RumyanaRuseva’s picture

    FileSize
    24.27 KB
    1.59 KB

    Sorry, wrong file name of the patch.

    andypost’s picture

    Status: Needs work » Needs review

    Lets run testbot, looks awesome

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

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

    Status: Needs review » Needs work

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

    gun_dose’s picture

    How to use this patch? I applied this and run drush updb but nothing changed.

    RumyanaRuseva’s picture

    gun_dose, this patch makes the facet work with ajax if the corresponding view is set to use ajax. There is no extra configuration. If it didn't work for you, maybe you had not set the View to use Ajax?

    I found another major problem now:
    When you add the facet block through admin/build/block and you change the machine name of the block so that it does not match the facet ID, it will not work.

    YurkinPark’s picture

    I realized that it doesn't work after first clicking on links

    gun_dose’s picture

    RumyanaRuseva, thank you for explanation! I supposed that it works as ajax_facets from D7, that provides ajax facet widgets and it led me on a false track :)

    YurkinPark’s picture

    Status: Needs work » Needs review
    FileSize
    24.38 KB
    584 bytes

    Fixing described bug about reattaching ajax links. BTW, why are we using custom replaceFacets AJAX command instead of core's? Maybe we could get rid of this?

    Status: Needs review » Needs work

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

    RumyanaRuseva’s picture

    Hi YurkinPark,
    I have not tested your patch yet, but at first glance it does not seem to be enough. As far as I saw the selectors were wrong when the block_id does not match the facet id, and it was not only a matter of calling Drupal.attachBehaviors().
    Unfortunately I haven't had time to debug and do more testing, I just reverted my block ids as a workaround.

    piyuesh23’s picture

    Ran into another issue while trying to use the module with search_api & DB as index. Its a race condition between the 2 AJAX requests:
    #1> To update views results
    #2> To update facet blocks.

    In case, facet blocks finish first, the facet checkboxes appear fine. But, in cases where views AJAX request finishes first, it leads to facets being rendered as links rather than checkboxes.

    Analysis:
    The checkboxes are added via JS written as a part of facets/drupal.facets.checkbox-widget library which is getting attached only with the views response & takes care of converting the facet blocks(which are available correctly in case of facet blocks request finishing up first). We would need to use AJAX Command that implements CommandWithAttachedAssetsInterface in order to make sure the libraries are attached correctly with the facets.

    I had added a TODO earlier around using invokeCommand(doesn't implement CommandWithAttachedAssetsInterface) in place of replaceCommand(implements CommandWithAttachedAssetsInterface) with custom JS function due to the issue in core mentioned at: https://www.drupal.org/node/736066

    Got it working fine with the patch attached here & the patch: https://www.drupal.org/files/issues/736066-324.patch. Attaching the updated patch here in case anyone else is running into the same problem.

    piyuesh23’s picture

    Missed removing instance of invokeCommand in the above patch. Uploading an updated patch.

    YurkinPark’s picture

    Remove this code as well then

     $.fn.replaceFacets = function(data) {
       if (data.replaceWith === '') {
         $(data.selector).html('');
       }
       else {
         $(data.selector).replaceWith(data.replaceWith);
       }
     };
    

    This command is useless now

    piyuesh23’s picture

    @YurkinPark, good catch. Removing this helper function also reminded me of handling a case where a facet block may disappear based on selection made for another facet & would never come back in case we remove the wrapper for the facet blocks. Retaining the feature in this patch as well.

    DanieleN’s picture

    Ironically the patches from piyuesh23 (#120, #121, #123) doesn't work for me. After click to a filter the ajax doesnt get triggered. Only a full page refresg

    Obviously, I'm missing something?

    • Ajax enabled in view setting
    • Block_ID is same as the Facet_ID

    Patch from YurkinPark at #117 ajax get triggert but the facet blocks stay the same.

    RumyanaRuseva’s picture

    piyuesh23, I can't believe that you just ignored half an year (50 comments) of progress on the patch and rolled the new one from 57, without even providing an interdiff to show what's removed. :(

    TBH, the new patch works for my case, except for the fatal error described in 107.

    piyuesh23’s picture

    Status: Needs work » Needs review
    FileSize
    23.99 KB
    2.43 KB

    @RumyanaRuseva, Apologies for not being clear in my comments above. The intent was to unblock anyone running into the same issue(using 8.x-alpha11 version of the module) & update this issue with a new patch based on the latest patch.

    Attaching patch & interdiff based on the patch in #119.

    P.S: This patch would introduce additional

    wrappers surrounding each facet block on each AJAX request leading to an un-necessary nested
    structure around each facet block(which is a known core issue https://www.drupal.org/node/736066). To avoid this issue with Drupal 8.4.5, use the patch here: https://www.drupal.org/files/issues/736066-324.patch. Also, as described in my comment #120, this is an edge case.

    To reproduce this one consistently, i had to add a timeout in facets-views-ajax.js around Drupal.ajax(facet_settings).execute();. This ensures the facet blocks get updated after completion of the views result AJAX request.

    Status: Needs review » Needs work

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

    piyuesh23’s picture

    Status: Needs work » Needs review
    FileSize
    24 KB
    1.91 KB

    Fixing the coding standard issues suggested by testbot.

    Status: Needs review » Needs work

    The last submitted patch, 128: ajax_facets-2826449-128.patch, failed testing. View results

    RumyanaRuseva’s picture

    RumyanaRuseva’s picture

    Thank you very much for the patch, piyuesh23, it seems to work great :)

    RumyanaRuseva’s picture

    Facet Summary block does not seem to work, and there are various errors:

    • In Block display of the view the Summary content is missing, and there is Notice: Undefined index: #attributes in Drupal\facets_summary\Plugin\Block\FacetsSummaryBlock->build() (line 104 of modules/contrib/facets/modules/facets_summary/src/Plugin/Block/FacetsSummaryBlock.php
    • In Page/embed view display the Summary content is visible, but it does not refresh. After changing the Facet selection there is an Error: Call to a member function getViewBuilder() on null in Drupal\facets\Controller\FacetBlockAjaxController->ajaxFacetBlockView() (line 171 of /modules/contrib/facets/src/Controller/FacetBlockAjaxController.php
    • After clicking any of the Summary links there is a js error TypeError: query.indexOf is not a function
    RumyanaRuseva’s picture

    I also noticed a missing 'use' clause, here is a fix for it.

    andypost’s picture

    Status: Needs review » Needs work

    The last submitted patch, 133: ajax_facets-2826449-133.patch, failed testing. View results

    jhuhta’s picture

    It seems to be problematic that we're just assuming the block id's to be the same as the facet id's (minus underscores) in FacetBlockAjaxController.php:

    $facets_block_id = str_replace('_', '', $block_id);
    

    In reality, $block_id holds the facet id, not block id as one could think. Is this on purpose?

    At least my facet blocks had different machine names, which broke updating of the block. I tried extracting the id from $block_selector, but in some cases there's a random string appended there so it wasn't very reliable. I'm not sure at this point what would be the better way to do it.

    couloir007’s picture

    The patch solves my issue of getting facets to reload results without a page reload, but the returned # of results does not adjust. Not sure if this is related.

    Thank you.

    Maico de Jong’s picture

    @jhuhta That was already 'fixed' in #70 but somehow reverted. I couldn't find a reason for the revert so attached is a patch that uses the 'block_id' saved in the block configuration on blockSubmit that was also already generated for existing blocks in hook_update()

    So please make sure you run database updates before testing this patch.

    couloir007’s picture

    @MDJ Webdiensten, this patch fixed my issue. One other thing I'm seeing though since I was going through the motions is that non ajax facets don't work when the patch is applied. I don't think this is a concern for me but thought I would pass that along.

    RumyanaRuseva’s picture

    Status: Needs work » Needs review
    FileSize
    3.3 KB
    24.46 KB

    Thank you MDJ Webdiensten for the updated patch. Your code was removed in #79 by niknak. I do not know if using block_id really fails in some cases, or he did not execute the update hook.

    I found 3 errors in the Facet Summary block. Here is a patch.

    couloir007, good catch, and that is critical to be fixed, of course. I fixed the widgets js to correctly trigger clicks on the hidden links, and it seems to work. I do not know if there's anything else broken.

    Status: Needs review » Needs work

    The last submitted patch, 140: ajax_facets-2826449-140.patch, failed testing. View results

    couloir007’s picture

    @RumyanaRuseva I just tested the new patch for non Ajax and both now work for me. Thank you.

    RumyanaRuseva’s picture

    I found that it doesn't work well with Contextual filters in the view.
    When the facet block is rendered by ajaxFacetBlockView(), it ignores the arguments and contains wrong result counts without applying the contextual filter. Refreshing the page shows the correct counts.
    I have no idea how to fix that.

    piyuesh23’s picture

    The patch for 8.x-1.0-alpha11 doesn't work with hierarchical facets e.g., taxonomy. The ajax callback gets attached only with the parent items & not the L2/L3 items. Needed this on a project using alpha11 version of the module.

    Adding it here for anyone else in the same situation.

    P.S.: I have not tested this yet with the dev version of the module, but anticipate the same issue there. Attaching interdiff as well to better explain the change.

    piyuesh23’s picture

    Seems like varnish cached the incorrect patch which i uploaded with the same filename earlier. Accessing https://www.drupal.org/files/issues/2018-04-04/facets-views-ajax-2826449... shows the correct patch content while https://www.drupal.org/files/issues/2018-04-04/facets-views-ajax-2826449... doesn't.

    Attaching another patch with a different filename.

    piyuesh23’s picture

    Another issue faced while using this patch with 8.x-1.0-alpha-11, where the facets generate incorrect links on pages with view blocks. So, my setup is like the following:
    - Views block with product listing
    - Facets with views block as data source.

    The problem while facets-block/ajax request is, it generates the path for facet filters as /facets-block/ajax?f[0]=... instead of using the page on which the view block & facet blocks are placed. Debugging this a little bit led to the reason being use of \Drupal::currentPath() instead of relying on the Request object to identify facet's source url.

    Adding a patch for people who facet this issue using alpha-11 version. Will soon test the same with the patch against dev & update that as well.

    flocondetoile’s picture

    Hi,

    Testing patch #146 with Facets beta2.

    Working fine for facets exposed as links.

    For facets exposed as checkboxes, I get this error

        base.js?v=8.5.3:13 Uncaught TypeError: Cannot read property 'indexOf' of undefined
        at Object.Drupal.Views.parseQueryString (base.js?v=8.5.3:13)
        at updateFacetsView (facets-views-ajax.js?p8d2ox:78)
        at HTMLLIElement.<anonymous> (facets-views-ajax.js?p8d2ox:68)
        at HTMLLIElement.dispatch (jquery.min.js?v=3.2.1:3)
        at HTMLLIElement.q.handle (jquery.min.js?v=3.2.1:3)

    The checkboxes seems to be a little broken (the soft limit doesn't work anymore)...
    ...Hum after several clear caches checkoxes seems to works fine now. But the soft limit still doesn't work

    For facets exposed as dropdown (select list), selecting a facet triggers a full page reload. Seems "normal" because facets-views-ajax.js seems to only trigger the click event for now.

    flocondetoile’s picture

    Trying to handle too facets exposed as dropdown. Attached patch #146 updated for a first attempt. Seems to work.

    RumyanaRuseva’s picture

    flocondetoile, the patch in #146 is incorrect, it deletes a lot of fixes in previous patches because it was rolled from #123 instead of #140. It seems that piyuesh23 is maintaining a version of the patch for alpha11 for his own needs.
    The latest working patch for beta2 is in #140. Please note that there is an update hook that needs to be executed before the changes can work.

    There are still several issues remaining:

    • The facets do not work correctly with contextual filters, they show wrong results counts in the facets and the summary block.
    • Exposed filter as block from a View Page does not get refreshed by the ajax.
    • Failing tests.
    flocondetoile’s picture

    Thanks for the input @RumyanaRuseva. I didn't well read the comments from #143 to #146.
    I will look at #140 then :-)

    Hiding more recent patch files than #140 from the summary to prevent others to make the same mistake I did.

    alanburke’s picture

    Running the latest patch through its paces.

    Just reiterating the point made by @flocondetoile that it doesn't work on dropdowns

    Alongside other issues in #149

    But it does look good - I'll be happy to test further patches.

    alanburke’s picture

    Update - it does work on dropdowns - I had a separate issue.

    It doesn't, however, work with
    https://www.drupal.org/project/facets_pretty_paths
    I know that won't be a blocker, but just pointing it out

    TuWebO’s picture

    Hello,
    Really nice this feature. Patch from #2826449-140: Ajax Facets blocks for views applies for me with limits commented in #2826449-149: Ajax Facets blocks for views .

    Not sure if dependant facets are working (not for me) with this patch.

    PFEnriquez’s picture

    Patch #140 does not work for me. The first time I click a checkbox (facet checkbox) the filters function, but I get this error (on javascript console):

    "
    An AJAX HTTP error occurred.
    HTTP Result Code: 500
    Debugging information follows.
    Path: /my-website/facets-block/ajax
    StatusText: 500 Service unavailable (with message)
    ResponseText: The website encountered an unexpected error. Please try again later.Symfony\Component\Routing\Exception\ResourceNotFoundException: No routes found for &quot;/facets-block/ajax&quot;. in Drupal\Core\Routing\Router-&gt;matchRequest() (line 125 of core/lib/Drupal/Core/Routing/Router.php). Drupal\Core\Routing\AccessAwareRouter-&gt;matchRequest(Object) (Line: 127)
    Drupal\facets\Controller\FacetBlockAjaxController-&gt;ajaxFacetBlockView(Object)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;Drupal\Core\EventSubscriber\{closure}() (Line: 582)
    Drupal\Core\Render\Renderer-&gt;executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;Drupal\Core\EventSubscriber\{closure}() (Line: 151)
    Symfony\Component\HttpKernel\HttpKernel-&gt;handleRaw(Object, 1) (Line: 68)
    Symfony\Component\HttpKernel\HttpKernel-&gt;handle(Object, 1, 1) (Line: 57)
    Drupal\Core\StackMiddleware\Session-&gt;handle(Object, 1, 1) (Line: 47)
    Drupal\Core\StackMiddleware\KernelPreHandle-&gt;handle(Object, 1, 1) (Line: 99)
    Drupal\page_cache\StackMiddleware\PageCache-&gt;pass(Object, 1, 1) (Line: 78)
    Drupal\page_cache\StackMiddleware\PageCache-&gt;handle(Object, 1, 1) (Line: 47)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware-&gt;handle(Object, 1, 1) (Line: 50)
    Drupal\Core\StackMiddleware\NegotiationMiddleware-&gt;handle(Object, 1, 1) (Line: 23)
    Stack\StackedHttpKernel-&gt;handle(Object, 1, 1) (Line: 664)
    Drupal\Core\DrupalKernel-&gt;handle(Object) (Line: 19)
    "

    The functionality is blocked and I can't select or unselect any checkbox.

    A drupal rod facets.block.ajax shows me the route exists.

    meanderix’s picture

    I was having a lot of trouble with the ajax progress indicator (throbber) not being removed when selecting multiple facets. I traced it to a the $(facet_item).children('a').click() method being triggered several times. Changing to $(facet_item).children('a').once().click() fixed this problem. (N.b. this patch is based on #140).

    StryKaizer’s picture

    +++ b/src/Widget/WidgetPluginBase.php
    @@ -52,6 +53,20 @@ abstract class WidgetPluginBase extends PluginBase implements WidgetPluginInterf
    +        // Additional check if facets are tied up with a block on the page.
    +        if ($result->getUrl()->getRouteName() === 'facets.block.ajax') {
    +          $request = \Drupal::request();
    +          $url_object = \Drupal::service('path.validator')
    +            ->getUrlIfValid($request->getPathInfo());
    +          if ($url_object) {
    +            $url = $result->getUrl();
    +            $options = $url->getOptions();
    +            $route_params = $url_object->getRouteParameters();
    +            $route_name = $url_object->getRouteName();
    +            $result->setUrl(new Url($route_name, $route_params, $options));
    +          }
    +        }
    +
    

    Can somebody let me know what this code does?
    @piyuesh23, it looks like this code was added in #34, any idea if this is still relevant?
    It breaks pretty paths, and I'm not sure this code is actually doing anything.

    I have pretty paths (with a patch) working with #155, patch at
    #2976820: Support AJAX views

    StryKaizer’s picture

    FileSize
    24.58 KB
    935 bytes

    I'll answer myself on #156, it looks like this is needed for facetsources being blocks.

    I adjusted the code to make sure it does not break pretty paths, and altered the comment to make it more clear why this code is there.

    Nick_vh’s picture

    Why you!

    Here's a little review already. Will try to comb through it further

    1. +++ b/js/checkbox-widget.js
      @@ -43,7 +43,7 @@
      +      $(this).siblings('a')[0].click();
      

      Is referring to 0 always ok? Don't we need an additional check to see if this value is even in there? Eg, could it give out of bounds somehow?

    2. +++ b/js/dropdown-widget.js
      @@ -37,7 +37,7 @@
      +      $dropdown.addClass('js-facets-dropdown');
      

      could break backwards compatibility. Please add the js-facets-dropdown on top of the facets-dropdown.

    3. +++ b/js/dropdown-widget.js
      @@ -68,7 +68,8 @@
      +        $(a)[0].click();
      

      Same comment as above. Could go out of bounds? Certainly if the ul.find somehow doesn't return any a link.

    4. +++ b/js/facets-views-ajax.js
      @@ -0,0 +1,214 @@
      + * Facets Views AJAX handling.
      

      Please add a better description of what the behavior is that this file is supporting.

    5. +++ b/js/facets-views-ajax.js
      @@ -0,0 +1,214 @@
      +   * Trigger views AJAX refresh on click.
      

      Which click?

    6. +++ b/js/facets-views-ajax.js
      @@ -0,0 +1,214 @@
      +        // Get the View for the current facet.
      

      loose the capital letter of the view

    7. +++ b/js/facets-views-ajax.js
      @@ -0,0 +1,214 @@
      +        var view, current_dom_id, view_path;
      

      Why not camelcasing the variables?

    StryKaizer’s picture

    Note to self (and others who might test this patch:

    Check what happens when browsing to an url with facets already active, which causes a given facetblock to be empty.
    Than unselect active items, facetblock should appear

    Haven't tested yet, but we need to take this usecase into account, not sure if current patch already does.

    5n00py’s picture

    Hi all.
    In [2943638] we have case that can break some of current progress.

    Main idea is to hide summary block when no items to show.

    tomasbarej’s picture

    We're using this patch currently on 3 ongoing projects and on 2 we had and issue that Facets ajax response was empty. Problem was caused when before execution of the controller FacetBlockAjaxController was called \Drupal::routeMatch()->getRouteName(). That causes that original route match was statically stored and wasn't replaced in FacetBlockAjaxController so Facets block plugin assumes that facets should not be rendered for called path. Therefore \Drupal::service('current_route_match')->resetRouteMatch(); has to be added before current route replacement starts.

    Clauce’s picture

    Hello,

    here is a use case of facets with the patch in #161 applied.
    I get this error :
    Notice: Undefined index: block_id in Drupal\facets\Plugin\Block\FacetBlock->build() (line 104 of modules/contrib/facets/src/Plugin/Block/FacetBlock.php).

    The ajax facet works the first time, but afterwards, I am unable to uncheck facet.

    I hope it will help improve this great and needed feature.

    RumyanaRuseva’s picture

    Hi Clauce,
    Did you run update.php (drush updb) after applying the patch? The error you mention should be fixed by the update.

    Clauce’s picture

    Hello RumyanaRuseva,

    I thank you for your help, saddly this didn't work, I still have the same error.
    It may be of any help : I have an ajax error in my console wich globaly says 500 Service unavailable.

    Thank you again

    PFEnriquez’s picture

    Patch #140 does not apply correctly anymore on last dev.

    Furthermore I think #162 is similar to my comment #154

    uzlov’s picture

    Issue in >
    @@ -81,11 +82,22 @@ class FacetBlock extends BlockBase implements ContainerFactoryPluginInterface {
    ...
    + if (!empty($build['#use_ajax']) && isset($facet_id)) {

    We don't need here the check of "&& isset($facet_id)", because we don't need it and already don't have this variable!
    Changes in commit >
    https://cgit.drupalcode.org/facets/commit/?id=42f04e7c66ab8f340d2027116e...

    please, check new patch

    uzlov’s picture

    Status: Needs work » Needs review
    Clauce’s picture

    Hello,

    Uzlov, I thank you for your help and reply.

    I took everything at the begining, installed the dev release (instead of the beta release and wich includes the changes in commit that you pointed) and applied complete patch #161 plus yours #166.

    I have no more errors, but still, all the facets checkbocks are disabled (selected and unselected options) after firts selection, making impossible to further use the facets. I feel - but it just an idea - that this issue come from the fact that, in non ajax context, facets are disabled after selection to prevent user from selecting another facet option while the ressources page reloads. I think I read some issue on it but I can not put my hand on it again.

    I would be glad to help more, but I am not much of a coder, sorry.
    I hope this use cas will help improve this already great work.

    Thank you

    borisson_’s picture

    Updated the patch a little, both to address @Nick_vh's feedback and to add some groundwork on adding tests. It also adds a fix for #159.

    Nick_vh’s picture

    Tested the patch and works as expected. Tried date range facets with simple config and author facet. Worked out of the box so this seems good to go for me!

    Any specific usecase you need me test further?

    borisson_’s picture

    FileSize
    5.76 KB
    36.6 KB

    I don't think we need to test any other usecases, that sounds like a good start. I added tests but haven't ran them locally yet. Let's see how broken they are. I also fixed the other testbreaks.

    borisson_’s picture

    FileSize
    4.39 KB
    38.13 KB

    Should be getting closer to green now.

    borisson_’s picture

    Issue tags: -Needs tests
    FileSize
    827 bytes
    38.33 KB

    The remaining functional tests should be green now. I think that leaves us with just the jstb-test.

    borisson_’s picture

    Ok, so all we need to do here is do another thorough review of the code, document it better if there are places where additional documentation will help and get the the javascript test to work. We should probably also extend the testcoverage.

    borisson_’s picture

    FileSize
    636 bytes
    38.34 KB
    borisson_’s picture

    FileSize
    38.34 KB
    borisson_’s picture

    FileSize
    38.36 KB
    borisson_’s picture

    FileSize
    38.4 KB
    borisson_’s picture

    FileSize
    38.4 KB

    Another try

    borisson_’s picture

    FileSize
    17.77 KB

    So, this was green locally. The problem existed between the keyboard and chair. Fingers crossed.

    borisson_’s picture

    FileSize
    38.6 KB

    • Nick_vh committed 14fb690 on 8.x-1.x authored by borisson_
      Issue #2826449 by piyuesh23, borisson_, RumyanaRuseva, gaydabura,...
    Nick_vh’s picture

    Status: Needs review » Fixed

    Wow! Thanks everyone. Committing :)

    sagesolutions’s picture

    Awesome! Thanks for fixing this!

    nor sairi’s picture

    im happy hear this :)

    qzmenko’s picture

    Status: Fixed » Needs work
    Related issues: +#2984151: Click on Default option in Dropdown widget is not working

    Hey, guys. This change seems to have broken the functionality of the drop-down widget that does not use ajax:

           // Go to the selected option when it's clicked.
           $dropdown.on('change.facets', function () {
    -        window.location.href = $(this).val();
    +        var a = $($ul).find("[data-drupal-facet-item-id='" + $(this).find(':selected').data('drupalFacetItemId') + "']");
    +        $(a)[0].click();
           });
    

    When you click on the default option, var a is empty in the drop-down list. Because of this, clicking on the default option does not work and the js error in the console appears:

    Uncaught TypeError: Cannot read property 'click' of undefined
        at HTMLSelectElement.<anonymous> (dropdown-widget.js?v=8.5.4:74)
        at HTMLSelectElement.dispatch (jquery.min.js?v=3.2.1:3)
        at HTMLSelectElement.q.handle (jquery.min.js?v=3.2.1:3)

    Referenced issue:
    #2984151: Click on Default option in Dropdown widget is not working

    andypost’s picture

    Status: Needs work » Fixed

    @qzmenko When issue is fixed just file follow-up and mention here, no reason to change status

    imperator_99’s picture

    Hi,

    Is there some kind of magic trick to get this to work? From what I can see, all I should have to do is set a view to use ajax, and then the facet will automatically pick that up. Currently, with a view set to use ajax, and a facet on the page, selecting checkboxes for tags triggers a page refresh as per the default behaviour. I get the same result with both plain views and views using contextual filters. There are no errors, PHP or JavaScript. I've run drush updatedb and the relevant update happened.

    Any advice?

    Thanks,
    Jesse.

    vacho’s picture

    I am review it and I found that when the block facet is added to block with site building method it is accomplish and well.

    Problems finded:
    - When the block facet is included by twig tpl
    {{ drupal_block('facet_block:job_category', wrapper=false) }}
    Ajax fail (checkboxes maintain blocked)

    - When the block facet is included inside a paragraph
    Ajax fail (checkboxes maintain blocked)

    voleger’s picture

    Is there any way how to keep view display use ajax but disable it for the facet block?

    asif_khan’s picture

    in panel ajax fails and option are disabled despite view block filters result.

    geek-merlin’s picture

    Status: Fixed » Closed (fixed)

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

    edurenye’s picture

    The summary block does not work after updating from beta3 to 1.0 because of this commit.

    borisson_’s picture

    @edurenye: we're not going to revert this, I would love it if you could open a new issue.

    edurenye’s picture

    florianmuellerCH’s picture

    In case anyone stumbles upon this: In my case, I found out that we used an overwritten block.html.twig template which does not print out the attributes and classes of default blocks and also not of the facets block. But these attributes were needed to replace the block with the reloaded facet.

    I copied the core/themes/stable/templates/block/block.html.twig to my custom theme as block--facet-block.html.twig to be used only by facets, and it worked again as expected.

    dbroll’s picture

    @voleger

    Is there any way how to keep view display use ajax but disable it for the facet block?

    I was able to accomplish this for my use case (needed views infinite scroll to have ajax but not facet blocks). By disabling the related js file from the facet module in my active theme's info.yml file:

    libraries-override:
      facets/drupal.facets.views-ajax: false