Well I spent a lot of hours looking how templates and other stuffs are related with knockout.js
, i will try to explain how subtotal price format is displayed to order summary at checkout module, but is same to other things too. My current version is Magento ver. 2.0.4.
First if you navigate to the corresponding layout file for checkout at
vendor/magento/module-checkout/view/frontend/layout/checkout_index_index.xml
you will see at line 392 inside cart_items
block the subtotal block like this:
As you can see , Magento calls a js template to display subtotal of product right after product details.
If you navigate to
vendor/magento/module-checkout/view/frontend/web/js/view/summary/subtotal.js
you will see at line 15 is called subtotal template , and a function called getValue()
,
getValue: function () {
return this.getFormattedPrice(this.getPureValue());
}
which later i saw it is called in subtotal template , which is located to
vendor/magento/module-checkout/view/frontend/web/template/summary/subtotal.html
with this code:
Subtotal.js
file uses
Magento_Checkout/view/frontend/web/js/view/summary/abstract-total.js
getFormattedPrice()
function, while this file uses
Magento_Checkout/view/frontend/web/js/model/quote.js getPriceFormat()
function read about require.js dependencies ,
which returns a price format, and here i saw that this variable is populated like this,
var priceFormat = window.checkoutConfig.priceFormat;
So where does window.checkoutConfig.priceFormat comes from?
Magento 2 did this:
If you navigate to
/vendor/magento/module-checkout/view/frontend/templates/onepage.phtml
at line 26 is initialized window.checkoutConfig with $block->getCheckoutConfig()
, which function is at
/vendor/magento/module-checkout/Block/Onepage.php
line 89, here it takes all config providers and returns them.
Where are config providers defined?
They are defined at
vendor/magento/module-checkout/etc/frontend/di.xml
at line 46, at sends us to
Magento\Checkout\Model\DefaultConfigProvider.php
which has getConfig()
function, at line 254 you can see getConfig()
function and at line 271 is priceFormat populated like this:
$output['priceFormat'] = $this->localeFormat->getPriceFormat(
null,
$this->checkoutSession->getQuote()->getQuoteCurrencyCode()
);
This means priceFormat is declared at populated here at getConfig()
function, so you can later use it with window.checkouConfig.priceFormat
.
I was working on applying place autocomplete on checkout an here is a snippet with my code:
<script src="https://maps.googleapis.com/maps/api/js?key=lll&libraries=places&callback=notifySubscribers"
async
defer></script>
<script>
var notifySubscribers = function () {
require(['GoogleAddressLookup/model/apiLoadListener'], function (loadListener) {
loadListener.isGoogleApiLoaded(true);
})
};
</script>
And my explanation. This phtml is rendered in after.body.start container and as you can see i basically do async load of google lib. The important part is that i pass callback function notifySubscribers. There as you can see i load my apiLoadListener class which is dedicated for holding information about the state of script in isGoogleApiLoaded ko observable. ApiLoadListener is by itself defined in separate file. Because isGoogleApiLoaded property is ko.observable then i can load apiListener module in any other module in which i can subscribe callback and execute appropriate logic. In your case it would be an initialization of google map on a particular element. I do it within onElementRender callback, here is an example snippet:
onElementRender: function (el) {
if (!loadListener.isGoogleApiLoaded()) {
loadListener.subscribe((isApiLoaded) => {
if (isApiLoaded) {
this.initializer = new Initializer(el, Strategy, this.autocomplete_id);
}
});
} else {
this.initializer = new Initializer(el, Strategy, this.autocomplete_id);
}
},
As you can see, disregarding the unknown classes, i am basically listening for event dispatch from apiLoader to perform my logic.
I hope that will help you out.
Best Answer
TL:DR
The template it calls is
magento/module-checkout/view/frontend/web/template/onepage.html
.My research is below.
What does this script do?
This informs Magento to call the JS layout if the
#checkout
element exists on the page.The above code tells Magento to render a template, now how does it know which template to render? If you look at the parent
div
you'll see this code:This is informing Magento that the nested code is in relation of the checkout (it does more than this but I'm not going too far into it).
Find the template
The template can be defined within the
text/x-magento-init
tag, but Magento don't usually do it this way as you can see. Magento usually do it via the XML method, which is what this line does:This gets the components configuration from the XML, so let's take a look at that.
If you search
vendor/magento/module-checkout/view/frontend/layout
foronepage.phtml
it should returnmagento/module-checkout/view/frontend/layout/checkout_index_index.xml
. So let's look in here for the config.Nested within
checkout.root
you will see a lot of<argument>
tags, if you look at this line -<item name="checkout" xsi:type="array">
this relates to the scope we saw earlier. Within this there is a line that defines a template:So this means the getTemplate() call is returning:
As you can tell by the XML file UI components can be pretty overwhelming, there is also a lot more that I've left out it could go on forever and I don't have a good understanding of all aspects yet. But hopefully this points you in the right direction.