Categories


Archives


Recent Posts


Categories


Magento 2: Finding Registered Knockout.js View Models and Templates

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

Another javascript debugging snippet for the intrepid Magento 2 javascript programmer. The Magento_Ui/js/core/app RequireJS module/application/program is an important part of Magento 2’s UI Component system. This is the program that registers KnockoutJS views and makes them available for use in the (custom to Magento 2) Knockout.js scope binding.

data-bind="scope: some-viewmodel"

While the binding process still remains a bit of a mystery, I’ve recently unearthed a way to view all the available Knockout.js view models.

reg = requirejs('uiRegistry')
reg.get(function(item){
    console.log(item.name);
    console.log(item);
});

The uiRegistry RequireJS module (pointing to Magento_Ui/js/lib/registry/registry by default (located in vendor/magento//module-ui/view/base/web/js/lib/registry/registry.js)) returns an object that’s a very fancy dictionary/array. This is the object that Magento registers view models to. You can fetch individual view models by name with code like this

reg.get('customer_listing.customer_listing');     

Or, as we have above, just pass in a javascript function as a callback to list every item in the registry.

reg = requirejs('uiRegistry')
reg.get(function(item){
    console.log(item.name);
    console.log(item);
});

The get method has a number of other ways to query for registered view models – the only documentation for this is in get’s comments. We’ll leave this as an exercise for the reader.

/**
 * Retrieves item from registry which matches specified search criteria.
 *
 * @param {(Object|String|Function|Array)} query - Search condition (see examples).
 * @param {Function} [callback] - Callback that will be invoked when
 *      all of the requested items are available.
 * @returns {*}
 *
 * @example Requesting item by it's name.
 *      var obj = {index: 'test', sample: true};
 *
 *      registry.set('first', obj);
 *      registry.get('first') === obj;
 *      => true
 *
 * @example Requesting item with a specific properties.
 *      registry.get('sample = 1, index = test') === obj;
 *      => true
 *      registry.get('sample = 0, index = foo') === obj;
 *      => false
 *
 * @example Declaring search criteria as an object.
 *      registry.get({sample: true}) === obj;
 *      => true;
 *
 * @example Providing custom search handler.
 *      registry.get(function (item) { return item.sample === true; }) === obj;
 *      => true
 *
 * @example Sample asynchronous request declaration.
 *      registry.get('index = test', function (item) {});
 *
 * @example Requesting multiple elements.
 *      registry.set('second', {index: 'test2'});
 *      registry.get(['first', 'second'], function (first, second) {});
 */

The three things you’re probably interested in are a Knockout.js view model’s name, component, and template

reg.get(function(item){        
    //customer_listing.customer_listing.listing_top.listing_filters.entity_id.to
    console.log(item.name);

    //Magento_Ui/js/form/element/abstract
    console.log(item.component);

    //ui/grid/filters/field
    console.log(item.template);
});    

The name is a view model’s identifier, and what you’ll use in the scope binding

data-bind="scope: customer_listing.customer_listing.listing_top.listing_filters.entity_id.to"

The component is the RequireJS module that defines the view model. The template is the (custom to Magento 2) remote Knockout.js template identifier.

Copyright © Alan Storm 1975 – 2017 All Rights Reserved

Originally Posted: 9th September 2016