Development Tips: Magento 2 AJAX Layered Navigation

Development Tips: Magento 2 AJAX Layered Navigation

Development Tips: Magento 2 AJAX Layered Navigation

It’s annoying for customers to filter products by different attributes and wait each time when the page reloads, isn’t it? But this is default Magento behavior.

In such a way, response time increases as server load becomes slower. Customers can be easily frustrated since they expect advanced navigation that is not limited to only one filter at a time.

So, to enhance the user experience, the thing we need to add is AJAX.

AJAX allows requesting and receiving data from the server side after a page has loaded. As a result, just the requested parts of the web page are updated.

This post will show you how to improve layered navigation by implementing AJAX method to the filters and the pagination blocks.

Step 1: Start from Entry Point

We find entry point for filtering and pagination of the catalog and search page:

/vendor/magento/module-catalog/view/frontend/web/js/product/list/toolbar.js

Step 2: Extend Widget

The idea of a process is that all customer’s clicks on filters and for page loading are tracked, and then the correspondent POST-query is made to receive the needed content to be later rendered on the page.

For this purpose, we need to extend the mage.productListToolbarForm widget.

Under app/code/Extait/AjaxNavigation/view/frontend/web/js/product/list/ directory, we create toolbar.js file containing the following:

define([
    "jquery",
    "jquery/ui",
    "Magento_Catalog/js/product/list/toolbar"
], function($) {
    'use strict';
    $.widget('mage.productListToolbarForm', $.mage.productListToolbarForm,
{
      _create: function () {
         //…
      },
      applyFilters: function (event) {
         //…
      },
      changeUrl: function (paramName, paramValue, defaultValue) {
         //…
      }
      
    });
     return $.mage.productListToolbarForm;
});

Step 3: Override Constructor

First we add our widget to the require-config.js file:

 var config = { 
      map: {
            '*': {
                   productListToolbarForm:
            'Extait_AjaxNavigation/js/product/list/toolbar',
             }
       }
};

And then we extend the constructor in the widget:

 _create: function () {
      this._super();
      $.extend(this.options, {
            filterItemControls: '.block.filter .item a, .block.filter .filter-clear,.block.filter .swatch-option-link-layered, .pages-items a'
      });

      $(this.options.filterItemControls)
             .off('click.' +this.namespace + 'productListToolbarForm')
                 .on('click.' +this.namespace + 'productListToolbarForm', {},
       $.proxy(this.applyFilters, this));
},

Now we can track links for filtering and pagination. As well, we implement applyFilters function the next way:

applyFilters: function (event) { 
    //make ajax call, render results and change url
    event.preventDefault();
},

Step 4: Redefine ChangeUrl Function

We should override the changeUrl function which is responsible for clicks, considering the way of rendering, sorting and other navigation elements on a catalog page.

changeUrl: function (paramName, paramValue, defaultValue) { 
    //make ajax call, render results and change url
}

After this, we use the history.replaceState(null, null, newUrl) function so that a page URL can be changed without the whole page reloading.

Step 5: Add Plugin to Return Json Response

On the server side, the Magento\Catalog\Controller\Category\View  class is used for catalog rendering. Therefore, we should override execute method so that it can return json response with the filter and product blocks. This is implemented with the following plugin:

<type name="Magento\Catalog\Controller\Category\View">
     <plugin name="Extait_AjaxNavigation_Category_View"
type="Extait\AjaxNavigation\Plugin\Category\View" />
</type>


class View
{
    //…
    public function aroundExecute(\Magento\Catalog\Controller\Category\View $subject, \Closure $method)
    {
         $response = $method();
         if ($response instanceof Page) {
              if ($subject->getRequest()->getParam('ajax') == 1) {
                   // return json result with page content
              }
         }
         return $response;
    }
}

As a result, we intercept the clicks and render the necessary data blocks with the help of JavaScript. By doing so, pages can run smoothly and quickly.

These 5 steps are sufficient to make our catalog work without page reloading.

We hope our tips were useful for quicker and better understanding of realizing AJAX feature in  Magento 2 layered navigation module.

Have any questions? You are free to leave a comment below. Thanks for reading!

Comments

© Extait, 2019