Magento 2 – Updating UI Library JavaScript

frontendjavascriptmagento2requirejs

How can i override default Mage 2 UI js functions? For example: I have setup accordion layered navigation to show/hide the filters in the sidebar (like the one in Luma theme). Default collapsible.js within UI library uses show() / hide(), but i wish to override this with jquery fadeIn / fadeOut methods.

Is there a way to override certain UI js parts without editing the core library, probably within template so the changes stay local?

Best Answer

Yes this is possible and quite easy to do.

On the layered navigation template you have a data-mage-init attribute on the element that contains the accordion where you can filter by various product attributes.

<div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init='{"accordion":{"openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false}}'>

You can see the call to accordion with options assigned to it. In this attribute, "accordion" is a requirejs mapping that points to the accordion file. You can find the actual mapping in vendor/magento/module-theme/view/frontend/requirejs-config.js.

To create your own mapping you must create your own requirejs-config.js file in the view/[frontend|base|adminhtml] directory. That file will look like this:

var config = {
    map: {
        "*": {
            "fadeInAccordion": "Namespace_Module/js/fade-in-accordion"
        }
    }
};

If you wanted your widget to be used globally, you would simply change "fadeInAccordion" to "accordion" and your widget would be used everywhere an accordion was initialized using the "accordion" mapping. This should show you the power and flexibility using require-js mappings provide over requiring a script by path.

Now you must create the fade-in-accordion.js file that fadeInAccordion maps too. That file will look like this:

<!-- language: lang-js -->
define([
    "jquery",
    "mage/accordion"
], function($){
    "use strict";

    $.widget("Namespace_Module.fadeInAccordion", $.mage.accordion, {
        activate: function () {
            if (!this.options.disabled) {
                if (this.options.animate) {
                    this.content.fadeIn();
                } else {
                    this.content.show();
                }
                this._open();
            }
        },
        deactivate: function () {
            if(this.options.animate) {
                this.content.fadeOut();
            } else {
                this.content.hide();
            }
            this._close();
        }
    });

    return $.Namespace_Module.fadeInAccordion;
});

The first parameter in the $.widget() function is arbitrary but it must match the return statement. The second parameter is the object you are inheriting. The third parameter is where you can create new functions or override inherited functions. The activate and deactivate are both inherited from the collapsible widget so you can edit/override them in your own widget.

To use your new widget you must create or edit a template and reference your js file either using the path or the mapping. Here is an example of overriding the layered navigation element to use your new widget.

<div class="filter-options" id="narrow-by-list" data-role="content" data-mage-init='{"fadeInAccordion":{"openedState": "active", "collapsible": true, "active": false, "multipleCollapsible": false}}'>

It is the same accordion as before but this one will fadein/out hidden containers instead of hide and show them.

This page on the Magento 2 devdocs will show you more info if needed: http://devdocs.magento.com/guides/v2.0/javascript-dev-guide/javascript/js_practice.html

Related Topic