The Knockout.js bootstrap module in Magento 2 includes the following module via a define dependency.
Magento_Ui/js/lib/knockout/extender/bound-nodes
Technically speaking, this module creates wrappers for the ko.applyBindings and ko.cleanNode methods. These wrappers will stash certain view models and nodes in a private javascript WeakMap, and then return a single registry object that will let you access items in the WeakMap.
However, it's not clear what end-user-programmer facing features this enables. Does anyone here know what the Magento_Ui/js/lib/knockout/extender/bound-nodes module is actually for? Or is familiar enough with Knockout.js internals to figure things out?
Bound-nodes returns object with methods that allows:
- get root node that associated with a model that you provide.
- subscribes to adding of nodes associated with a model
- subscribes to removal of nodes associated with a model
- removes subscriptions from the modal
Also we have /Magento/Ui/view/base/web/js/lib/view/utils/async.js that use bound-nodes functionality and you can find a lot of usages it in Magento.
Thank you omiroshnichenko -- that's useful information and a good start, but it's still not quite clear what you mean when you say
get root node that associated with a model that you provide
What is a "root node"? What does "associated" mean? My first impressions is you're saying the bound-nodes module can return which HTML-DOM nodes are "scoped" with a particular view model. However, if I try something like this on the homepage of a Magento 2.1.1 instance running the Luma theme
boundNodes = requirejs('Magento_Ui/js/lib/knockout/extender/bound-nodes'); reg = requirejs('uiRegistry'); viewModel = reg.get('customer'); console.log( boundNodes.get(viewModel) );
An empty array is returned. i.e. the customer view model is not "associated" with any nodes, despite the customer view model being scoped in the HTML source with
<li class="greet welcome" data-bind="scope: 'customer'"> <!-- ko if: customer().fullname --> <span data-bind="text: new String('Welcome, %1!').replace('%1', customer().firstname)"> </span> <!-- /ko --> <!-- ko ifnot: customer().fullname --> <span data-bind="html:'Default welcome msg!'"></span> <!-- /ko --> </li>
Similarly, if we try to view the minicart_content view model
boundNodes = requirejs('Magento_Ui/js/lib/knockout/extender/bound-nodes'); reg = requirejs('uiRegistry'); viewModel = reg.get('minicart_content'); console.log( boundNodes.get(viewModel) );
a two element array is returned
[div.block-title, div.block-content]
However, the minicart_content is scoped in two different nodes
<a class="action showcart" href="http://magento-2-1-1.dev/checkout/cart/" data-bind="scope: 'minicart_content'"> <span class="text">My Cart</span> <span class="counter qty empty" data-bind="css: { empty: !!getCartParam('summary_count') == false }, blockLoader: isLoading"> <span class="counter-number"><!-- ko text: getCartParam('summary_count') --><!-- /ko --></span> <span class="counter-label"> <!-- ko if: getCartParam('summary_count') --> <!-- ko text: getCartParam('summary_count') --><!-- /ko --> <!-- ko i18n: 'items' --><!-- /ko --> <!-- /ko --> </span> </span> </a> <div id="minicart-content-wrapper" data-bind="scope: 'minicart_content'"> <!-- ko template: getTemplate() --><!-- /ko --> </div>
So, this is either a bug in the bound-nodes module or (more likely) when you're saying "associated" you don't mean scope -- you mean something else. However, it's unclear what that something else means.
Can you explain what that something else means? Or am I correct that this is a bug in the behavior of bound-nodes? Or some other, third thing.
Thanks again for your participation and your help!
Thank you alanstorm for detailed examples. Thats was very helpful. You understood correctly, bound-nodes module returns which HTML-DOM nodes are "scoped"(attached, binded, associated) with a particular view model. After investigation on yours examples, i have found a bug. In bound-nodes we have wrapper for applyBindings method that register model and node. But in custom scope binding we use applyBindingsToDescendant that did not wrapped. In case of minicart, you have result nodes form content.html template that minicart use. I have create a ticket and we will fix it in nearest release. Thanks.