Selecting date causes page reload when AJAX is enabled

Created on 5 April 2022, over 2 years ago
Updated 2 July 2024, 5 months ago

Problem/Motivation

When the view of search results has AJAX enabled, using other facets (such as checkboxes) prompts an AJAX reload, but using the date range facets prompts a full page reload.

Steps to reproduce

  • Basic setup:
    • Set up a fresh Drupal 9 site with facets_date_range enabled.
    • Set up a content type with a date field and a boolean field.
    • Create a few nodes with different field values.
    • Set up a database search server, search index, and view of the search index with a page display.
    • Set up a Date Range facet for the date field and a checkbox facet for the boolean field.
    • Add the facet blocks to the search page.
  • Key steps to reproduce the bug:
    • In the view of the search index, set Advanced > Other > Use AJAX to Yes.
    • On the search page, check a box for the boolean facet.
      • A spinner appears and the content updates (good).
    • Now select a date in the date range facet.
      • No spinner. Firefox's developer tools (Network tab) shows that a request occurred.

Proposed resolution

Maybe use Drupal.ajax(…).execute() and window.history.pushState(…) like in facets/js/facets-views-ajax.js?

🐛 Bug report
Status

Needs review

Version

1.0

Component

Code

Created by

🇺🇸United States jlstrecker Athens, Ohio, USA

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇮🇹Italy reinchek Napoli 🌋, 🇮🇹

    Hi, i'm having same issue.
    As you said the problem is caused by:
    window.location.href = facetUrl.replace("__date_range_min__", min).replace("__date_range_max__", max);
    causing the full page reload.

    For now i've resolved (look at the attached patch) this by calling, inside the autoSubmit() function, the function updateFacetsView() of `Drupal.behaviors.facetsViewsAjax` library. But to do this it's also needed to move the "Helper funciton" updateFacetsView() inside the Drupal.behaviors.facetsViewsAjax object.

    For the sake of completeness, I enclose the changes made within `facets/js/facets-views-ajax.js` (drupal/facets:1.6.0):

    diff --git a/modules/contrib/facets/js/facets-views-ajax.js b/modules/contrib/facets/js/facets-views-ajax.js
    --- a/modules/contrib/facets/js/facets-views-ajax.js
    +++ b/modules/contrib/facets/js/facets-views-ajax.js	(date 1695895680257)
    @@ -17,6 +17,7 @@
        */
       Drupal.behaviors.facetsViewsAjax = {
         attach: function (context, settings) {
    +      var helpers = this;
    
           // Loop through all facets.
           $.each(settings.facets_views_ajax, function (facetId, facetSettings) {
    @@ -38,10 +39,10 @@
             }
    
             // Update view on summary block click.
    -        if (updateFacetsSummaryBlock() && (facetId === 'facets_summary_ajax')) {
    +        if (helpers.updateFacetsSummaryBlock() && (facetId === 'facets_summary_ajax')) {
               $('[data-drupal-facets-summary-id=' + facetSettings.facets_summary_id + ']').find('a').once('facets_summary_ajax_link').click(function (e) {
                 e.preventDefault();
    -            updateFacetsView($(this).attr('href'), current_dom_id, view_path);
    +            helpers.updateFacetsView($(this).attr('href'), current_dom_id, view_path);
                 // Remove clicked element, ajax callback will update the content.
                 $(this).parents('li').remove();
               });
    @@ -54,112 +55,126 @@
                   $(facet_item).on('facets_filter.facets', function (event, url) {
                     $('.js-facets-widget').trigger('facets_filtering');
    
    -                updateFacetsView(url, current_dom_id, view_path);
    +                helpers.updateFacetsView(url, current_dom_id, view_path);
                   });
                 }
               });
    
             }
           });
    -    }
    -  };
    +    },
    
    -  // Helper function to update views output & Ajax facets.
    -  var updateFacetsView = function (href, current_dom_id, view_path) {
    -    // Refresh view.
    -    var views_parameters = Drupal.Views.parseQueryString(href);
    -    var views_arguments = Drupal.Views.parseViewArgs(href, 'search');
    -    var views_settings = $.extend(
    -        {},
    -        Drupal.views.instances['views_dom_id:' + current_dom_id].settings,
    -        views_arguments,
    -        views_parameters
    -    );
    +    // Helper function to update views output & Ajax facets.
    +    updateFacetsView: function (href, current_dom_id, view_path) {
    +      // Refresh view.
    +      var views_parameters = Drupal.Views.parseQueryString(href);
    +      var views_arguments = Drupal.Views.parseViewArgs(href, 'search');
    +      var views_settings = $.extend(
    +          {},
    +          Drupal.views.instances['views_dom_id:' + current_dom_id].settings,
    +          views_arguments,
    +          views_parameters
    +      );
    
    -    // Update View.
    -    var views_ajax_settings = Drupal.views.instances['views_dom_id:' + current_dom_id].element_settings;
    -    views_ajax_settings.submit = views_settings;
    -    views_ajax_settings.url = view_path + '?q=' + href;
    +      // Update View.
    +      var views_ajax_settings = Drupal.views.instances['views_dom_id:' + current_dom_id].element_settings;
    +      views_ajax_settings.submit = views_settings;
    +      views_ajax_settings.url = view_path + '?q=' + href;
    
    -    Drupal.ajax(views_ajax_settings).execute();
    +      Drupal.ajax(views_ajax_settings).execute();
    
    -    // Update url.
    -    window.historyInitiated = true;
    -    window.history.pushState(null, document.title, href);
    +      // Update url.
    +      window.historyInitiated = true;
    +      window.history.pushState(null, document.title, href);
    
    -    // ToDo: Update views+facets with ajax on history back.
    -    // For now we will reload the full page.
    -    window.addEventListener("popstate", function (e) {
    -      if (window.historyInitiated) {
    -        window.location.reload();
    -      }
    -    });
    +      // ToDo: Update views+facets with ajax on history back.
    +      // For now we will reload the full page.
    +      window.addEventListener("popstate", function (e) {
    +        if (window.historyInitiated) {
    +          window.location.reload();
    +        }
    +      });
    
    -    // Refresh facets blocks.
    -    updateFacetsBlocks(href);
    -  }
    +      // Refresh facets blocks.
    +      this.updateFacetsBlocks(href);
    +    },
    
    -  // Helper function, updates facet blocks.
    -  var updateFacetsBlocks = function (href) {
    -    var settings = drupalSettings;
    -    var facets_blocks = facetsBlocks();
    +    // Helper function, updates facet blocks.
    +    updateFacetsBlocks: function (href) {
    +      var settings = drupalSettings;
    +      var facets_blocks = this.facetsBlocks();
    
    -    // Remove All Range Input Form Facet Blocks from being updated.
    -    if(settings.facets && settings.facets.rangeInput) {
    -      $.each(settings.facets.rangeInput, function (index, value){
    -        delete facets_blocks[value.facetId];
    -      });
    -    }
    +      // Remove All Range Input Form Facet Blocks from being updated.
    +      if(settings.facets && settings.facets.rangeInput) {
    +        $.each(settings.facets.rangeInput, function (index, value){
    +          delete facets_blocks[value.facetId];
    +        });
    +      }
    
    -    // Update facet blocks.
    -    var facet_settings = {
    -      url: Drupal.url('facets-block-ajax'),
    -      submit: {
    -        facet_link: href,
    -        facets_blocks: facets_blocks
    -      }
    -    };
    +      // Update facet blocks.
    +      var facet_settings = {
    +        url: Drupal.url('facets-block-ajax'),
    +        submit: {
    +          facet_link: href,
    +          facets_blocks: facets_blocks
    +        }
    +      };
    
    -    // Update facets summary block.
    -    if (updateFacetsSummaryBlock()) {
    -      facet_settings.submit.update_summary_block = true;
    -      facet_settings.submit.facet_summary_plugin_id = $('[data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax.facets_summary_id + ']').data('drupal-facets-summary-plugin-id');
    -      facet_settings.submit.facet_summary_wrapper_id = settings.facets_views_ajax.facets_summary_ajax.facets_summary_id;
    -    }
    +      // Update facets summary block.
    +      if (this.updateFacetsSummaryBlock()) {
    +        facet_settings.submit.update_summary_block = true;
    +        facet_settings.submit.facet_summary_plugin_id = $('[data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax.facets_summary_id + ']').data('drupal-facets-summary-plugin-id');
    +        facet_settings.submit.facet_summary_wrapper_id = settings.facets_views_ajax.facets_summary_ajax.facets_summary_id;
    +      }
    
    -    Drupal.ajax(facet_settings).execute();
    -  };
    +      Drupal.ajax(facet_settings).execute();
    +    },
    
    -  // Helper function to determine if we should update the summary block.
    -  // Returns true or false.
    -  var updateFacetsSummaryBlock = function () {
    -    var settings = drupalSettings;
    -    var update_summary = false;
    +    // Helper function to determine if we should update the summary block.
    +    // Returns true or false.
    +    updateFacetsSummaryBlock: function () {
    +      var settings = drupalSettings;
    +      var update_summary = false;
    
    -    if (settings.facets_views_ajax.facets_summary_ajax) {
    -      update_summary = true;
    -    }
    +      if (settings.facets_views_ajax.facets_summary_ajax) {
    +        update_summary = true;
    +      }
    
    -    return update_summary;
    -  };
    +      return update_summary;
    +    },
    +
    
    -  // Helper function, return facet blocks.
    -  var facetsBlocks = function () {
    -    // Get all ajax facets blocks from the current page.
    -    var facets_blocks = {};
    +    // Helper function, return facet blocks.
    +    facetsBlocks: function () {
    +      // Get all ajax facets blocks from the current page.
    +      var facets_blocks = {};
    
    -    $('.block-facets-ajax').each(function (index) {
    -      var block_id_start = 'js-facet-block-id-';
    -      var block_id = $.map($(this).attr('class').split(' '), function (v, i) {
    -        if (v.indexOf(block_id_start) > -1) {
    -          return v.slice(block_id_start.length, v.length);
    -        }
    -      }).join();
    -      var block_selector = '#' + $(this).attr('id');
    -      facets_blocks[block_id] = block_selector;
    -    });
    +      $('.block-facets-ajax').each(function (index) {
    +        var block_id_start = 'js-facet-block-id-';
    +        var block_id = $.map($(this).attr('class').split(' '), function (v, i) {
    +          if (v.indexOf(block_id_start) > -1) {
    +            return v.slice(block_id_start.length, v.length);
    +          }
    +        }).join();
    +        var block_selector = '#' + $(this).attr('id');
    +        facets_blocks[block_id] = block_selector;
    +      });
    
    -    return facets_blocks;
    +      return facets_blocks;
    +    },
    +
    +    // Helper function to add exposed form data to facets url
    +    addExposedFiltersToFacetsUrl: function (href, view_name, view_display_id) {
    +      var $exposed_form = $('form#views-exposed-form-' + view_name.replace(/_/g, '-') + '-' + view_display_id.replace(/_/g, '-'));
    +
    +      var params = Drupal.Views.parseQueryString(href);
    +
    +      $.each($exposed_form.serializeArray(), function () {
    +        params[this.name] = this.value;
    +      });
    +
    +      return href.split('?')[0] + '?' + $.param(params);
    +    }
       };
    
       /**
    @@ -188,26 +203,13 @@
           });
    
           if (reload) {
    -        href = addExposedFiltersToFacetsUrl(href, options.extraData.view_name, options.extraData.view_display_id);
    -        updateFacetsBlocks(href);
    +        href = this.addExposedFiltersToFacetsUrl(href, options.extraData.view_name, options.extraData.view_display_id);
    +        this.updateFacetsBlocks(href);
           }
         }
    
         // Call the original Drupal method with the right context.
         beforeSend.apply(this, arguments);
    -  }
    -
    -  // Helper function to add exposed form data to facets url
    -  var addExposedFiltersToFacetsUrl = function (href, view_name, view_display_id) {
    -    var $exposed_form = $('form#views-exposed-form-' + view_name.replace(/_/g, '-') + '-' + view_display_id.replace(/_/g, '-'));
    -
    -    var params = Drupal.Views.parseQueryString(href);
    -
    -    $.each($exposed_form.serializeArray(), function () {
    -      params[this.name] = this.value;
    -    });
    -
    -    return href.split('?')[0] + '?' + $.param(params);
       };
    
     })(jQuery, Drupal);
    
  • 🇮🇹Italy reinchek Napoli 🌋, 🇮🇹
  • 🇮🇹Italy reinchek Napoli 🌋, 🇮🇹

    I've made i mistake forgotting to say that this patch works only if the patch " #3273136 - Selecting date clears other facet values when using AJAX " was previous applied.

    I've rewrited the patch removing some console.log.

  • 🇮🇹Italy reinchek Napoli 🌋, 🇮🇹

    Sorry for the shitpatch... but i'm doing these changes while working... I've added in this new patch a fix.

    PS: I've hided bad patches and leaved visible only the correct one.

  • Status changed to Needs review 5 months ago
  • 🇺🇸United States jrb Raleigh-Durham Area, NC, USA

    This attached patch makes the Date Range Facet widget work correctly with Ajax. It does not require the patch in #3273136: Selecting date clears other facet values when using AJAX and should fix that issue as well.

    It uses the trigger() method with the facets_filter event, the same way the other Facets widgets do. I believe this is the recommended way to make Facets work with JavaScript / Ajax.

Production build 0.71.5 2024