6

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?

5

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

  • Thanks Nathan for your answer. I have tried to recreate this setup on the template level by adding the requirejs-config.js in the theme dir root and then call the custom js from web/js/ folder (so the scope of custom functions stays local within the theme). The script loads up fine on the frontend but all the tabs are expanded. – g5wx Jan 8 '16 at 10:03
  • If you are wanting to use the tabs widget, your js will need to be different than what I have in my answer. The dependency "mage/accordion" needs to change to "mage/tabs" and $.mage.accordion needs to change to $.mage.tabs. Here is some more documentation about the tab's widget: devdocs.magento.com/guides/v2.0/javascript-dev-guide/widgets/… – Nathan Toombs Jan 8 '16 at 15:27
  • I wish to modify collapsible.js, which uses activate and deactivate functions to control the visibility methods. – g5wx Jan 8 '16 at 16:19
  • In that case you can extend the collapsible widget directly. Both the tabs and accordion widget inherit the collapsible widget so my above widget would still work to override the activate/deactivate functions. I haven't tested those functions so they may need some modification to get the effect you are looking for but the above method is the correct way to override widget functions. – Nathan Toombs Jan 8 '16 at 16:47
  • Yep, your answer led me to the right direction. Thank you for detailed explanation, helped a lot :) – g5wx Jan 9 '16 at 8:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.