Resolving Magento 2 Extension Conflict Between Amasty_Shopby and Amasty_Scroll

Resolving Magento 2 Extension Conflict Between Amasty_Shopby and Amasty_Scroll

10 min read

Send to you:

Magento® 2 developers usually try to choose extensions from a single creator so no conflicts arise between them. But what should you do if a conflict still arises where it shouldn’t? Today we will consider this situation as we have experienced it. We will show how to resolve Magento 2 extension conflict between two Amasty modules. Navigate using the list below:

Suppose there’s a site on Magento 2. It should support the AJAX filtration and infinite scrolling on products listing using AJAX (henceforth referred to as Infinite Scroll).

Amasty Modules Chosen

We chose extensions from Amasty to implement both functionalities: Improved Layered Navigation (Amasty_Shopby) and Infinite Scroll (Amasty_Scroll). We chose these extensions from the same developer on the basis of minimizing conflicts between them, since they affect the same pages: product listings.

Magento Extension Conflict Issues

When testing the site, a problem was identified in the listing. The Amasty Ajax Scroll extension places the following block in the footer:

<div class="amscroll-navbar" id="amscroll-navbar" style="background: #3A4F62;"><span class="amscroll-navbar-text">PAGE <span id="amscroll-navbar-current">1</span> of 15</span><a class="amscroll-navbar-link"></a></div>

This block has a fixed position and lets users know how many pages of products were loaded. If the category or search result returns only one page, the block shouldn’t be shown.

If the aforementioned situation occurred when a filter was applied using AJAX (for example, if a customer wanted to browse only products that are the color black and the results fit on just one page), then this block remained in the browser window, which confused users.

This had to be fixed, and we set out analyzing the code of both modules. Both modules for calling and processing Ajax requests implement jQuery widgets. jQuery widgets are Javascript objects with Function() type. The modules are synchronized in the following way.

mage.amScrollScript widget from Amasty_Scroll has the following constructor:

_create: function (options) {
    var self = this;
    $(document).on( "amscroll_refresh", function() {
        self._initialize();//run jQuery(document).trigger('amscroll_refresh');
    });
    this._initialize();
}

In Amasty_Shopby extension widgets, the”amscroll_refresh” event is called when processing AJAX response, but in Amasty_Scroll this event is processed by reinitialization of the whole widget.

So why doesn’t deleting the block from the footer take place when processing this event?

We got the answer to this question after carrying out the analysis of _initialize() method and the widget code.

_initialize: function () {
    this.next_data_cache = "";
    this.pagesLoaded = [];
    this._initPagesCount();
    this.disabled = 1;
    var isValidConfiguration = this._validate();
    if (!isValidConfiguration) {
        return;
    }
    this.disabled = 0;
    this.type = this.options['actionMode'];
    this._preloadPages();
    this._hideToolbars();
    var self = this;
    $(window).scroll(function() {
        self._initPaginator();
    });
    setTimeout(function(){
        self._initPaginator();
    }, 7000);
    this._initProgressBar();
},
….
_validate: function () {
    if(!this.options['product_container']
        || $(this.options['product_container']).length === 0
    ){
        console.log('Please specify "Products Group" Dom selector in module settings.');
        return false;
    }
    if (this.pagesCount <= 1) {
        return false;
    }
    return true;
},
...
_initProgressBar: function () {
    if (this.options['progressbar'] && this.options['progressbar']['enabled'] == '1') {
        var progressbar = jQuery('<div/>', {
            class: 'amscroll-navbar',
            id   : 'amscroll-navbar',
            style: this.options['progressbar']['styles']
        });
        var text = this.options['progressbarText'];
        text = text.replace('%1', '<span id="amscroll-navbar-current">'   this.currentPage   '</span>');
        text = text.replace('%2', this.pagesCount);
        progressbar.append('<span class="amscroll-navbar-text">'   text   '</span>');
        var linkElement = jQuery('<a/>', {
            class: 'amscroll-navbar-link'
        });
        linkElement.click(function(){
            $('body, html').animate({
                scrollTop: 0
            }, 300);
        });
        progressbar.append(linkElement);
        $("body").append(progressbar);
    }
}<

As you can see, the _initProgressBar method generates the aforementioned block and is called from the _initialize() method. However, _initProgressBar will not be called if the number of pages is equal to 1. This is verified in the _validate() method. The code for deleting the block created when applying an Ajax filter from Amasty_Shopby was not provided in the mage.amScrollScript widget. Amasty must correct this mistake.

Solving Amasty Module Conflicts in Magento 2

Mixin should be used for customizing Magento 2 jQuery widgets without rewriting the original widgets. We will declare it in the requirejs-config.js module file.

var config = {
    config:{
            mixins:{
                "Amasty_Scroll/js/amscroll":{
                    "Web4pro_Ajax/js/amscroll":true,
            }
        }
    },
...
}

Then we implement the mixin. We think it should be done as follows:

define([
    "jquery"
], function ($){
    return function (widget) {
        widget.prototype._initialize =function(){
                this.next_data_cache = "";
                this.pagesLoaded = [];
                this._initPagesCount();
                this.disabled = 1;
                var isValidConfiguration = this._validate();
                if (!isValidConfiguration) {
                    $('.amscroll-navbar').each(function(){
                        this.parentElement.removeChild(this);
                    })
                    return;
                }
                this.disabled = 0;
                this.type = this.options['actionMode'];
                this._preloadPages();
                this._hideToolbars();
                var self = this;
                $(window).scroll(function() {
                    self._initPaginator();
                });
                setTimeout(function(){
                    self._initPaginator();
                }, 7000);
                this._initProgressBar();
            };
    }
});

If the number of pages is equal to 1, all blocks with the amscroll-navbar class will be deleted from the DOM page. But this mixin won’t work, since the widget always has the NULL value. This is because Amasty implemented the mage.amScrollScript widget based on jQuery standards, not Magento 2 standards. If the widget was implemented based on Magento 2 standards, it would return a self-pointer using:

return $.mage.amScrollScript;

This is not seen in the code of the mage.amScrollScript widget. But a solution to this problem does exist, and it looks as follows:

define([
    "jquery"
], function ($){
    return function (widget) {
        $.mage.amScrollScript.prototype._initialize =function(){
                this.next_data_cache = "";
                this.pagesLoaded = [];
                this._initPagesCount();
                this.disabled = 1;
                var isValidConfiguration = this._validate();
                if (!isValidConfiguration) {
                    $('.amscroll-navbar').each(function(){
                        this.parentElement.removeChild(this);
                    })
                    return;
                }
                this.disabled = 0;
                this.type = this.options['actionMode'];
                this._preloadPages();
                this._hideToolbars();
                var self = this;
                $(window).scroll(function() {
                    self._initPaginator();
                });
                setTimeout(function(){
                    self._initPaginator();
                }, 7000);
                this._initProgressBar();
            };
    }

This alteration successfully deletes the block with the page number from the DOM page when it’s needed.

SUM MARY

Now you know that it could be a situation when choosing some modules you try to set them up, and conflict could appear because of the incompatibility of modules. We hope that our tutorial on how to resolve Magento 2 extension conflict was helpful and you can implement changes to your Magento 2 store. However, if you still have questions on how to solve module conflict or other problems regarding Magento 2 Extension Development, we are here to help you. Write us at [email protected], and we will take care of your project!

Posted on: May 31, 2018

3.7/5.0

Article rating (3 Reviews)

Do you find this article useful? Please, let us know your opinion and rate the post!

  • Not bad
  • Good
  • Very Good
  • Great
  • Awesome