Magento 2 UI components and listener

In this short and simple example we will explain how to create listener in Magento 2 UI component. We will explain it on built in Magento 2 UI component Columns which use component Magento_Ui/js/grid/listing (part of admin grid interface).

This file listing.js represents knockoutjs viewmodel of our component “Columns“. Let’s start with an explanation. Take a look at our listing.js code:

define([
    'ko',
    'underscore',
    'Magento_Ui/js/lib/spinner',
    'rjsResolver',
    'uiLayout',
    'uiCollection'
], function (ko, _, loader, resolver, layout, Collection) {
    'use strict';
 
    return Collection.extend({
        defaults: {
            template: 'ui/grid/listing',
            stickyTmpl: 'ui/grid/sticky/listing',
            viewSwitcherTmpl: 'ui/grid/view-switcher',
            positions: false,
            displayMode: 'grid',
            displayModes: {
                grid: {
                    value: 'grid',
                    label: 'Grid',
                    template: '${ $.template }'
                }
            },
            dndConfig: {
                name: '${ $.name }_dnd',
                component: 'Magento_Ui/js/grid/dnd',
                columnsProvider: '${ $.name }',
                enabled: true
            },
            editorConfig: {
                name: '${ $.name }_editor',
                component: 'Magento_Ui/js/grid/editing/editor',
                columnsProvider: '${ $.name }',
                dataProvider: '${ $.provider }',
                enabled: false
            },
            resizeConfig: {
                name: '${ $.name }_resize',
                columnsProvider: '${ $.name }',
                component: 'Magento_Ui/js/grid/resize',
                enabled: false
            },
            imports: {
                rows: '${ $.provider }:data.items'
            },
            listens: {
                elems: 'updatePositions updateVisible',
                '${ $.provider }:reload': 'onBeforeReload',
                '${ $.provider }:reloaded': 'onDataReloaded'
            },
            modules: {
                dnd: '${ $.dndConfig.name }',
                resize: '${ $.resizeConfig.name }'
            },
            tracks: {
                displayMode: true
            },
            statefull: {
                displayMode: true
            }
        }
...

In our listing.js class you will notice configuration for listener in “defaults” objects as property “listens“:

listens: {
                elems: 'updatePositions updateVisible',
                '${ $.provider }:reload': 'onBeforeReload',
                '${ $.provider }:reloaded': 'onDataReloaded'
            }

What doest it mean?

When provider (data source), in our case class “Magento_Ui/js/grid/provider“, fires event “reload” with method “this.trigger(‘reload’)” then callback method “onBeforeReload” will be called in our component “Magento_Ui/js/grid/listing“.

Also, when request in providers method reload is resolved (done), then “onReload” method is called and in “onReload” method event “reloaded” is fired. That triggers callback method “onDataReloaded” in viewmodel of component “Columns”.

If you take a look on provider js file you will see exactly where provider class fires events:

reload: function (options) {
            var request = this.storage().getData(this.params, options);
 
            //call to callback method onBeforeReload
            this.trigger('reload');
 
            request
                .done(this.onReload)
                .fail(this.onError);
 
            return request;
        },
onReload: function (data) {
            this.firstLoad = false;
 
            //call to calback method onDataReloaded
            this.setData(data)
                .trigger('reloaded');
        }

In method “onReload” event “reloaded” is fired by method “trigger(‘reloaded’)“.

Reload method in provider class is triggered always when UI component loads data from Magento 2 backend.

I hope that you understand our explanation and that you understand how it works.