x-magento-template and mage/template
Sometimes underscore.js templates are used in Luma.
Most of the time this happens through the utility JavaScript module mage/template
.
Since mage/template
and underscore.js are not used in Hyvä, these template-snippets are replaced with Alpine.js templates.
Underscore templates are useful to create new DOM nodes for each item in an array.
They might also be used for the plain rendering some data available in JavaScript in HTML, but that use case is not covered here since it can be replaced by plain Alpine.js directives like x-html
and x-text
.
In Alpine.js array items are rendered using x-for
directives.
Recap of mage/template
It is helpful to have some understanding of Luma code when converting it to Alpine.js.
In this spirit, this mage/template
recap is intended to help you in the conversion process.
Commonly the templates are written as <script id="selector" type="text/x-magento-template">
elements in .phtml files.
The selector is often an ID attribute, but sometimes it can also be a something like data-role="myTemplate"
.
Here is an example of how mage/template
is used in Luma (in the following example it is assigned to the template
variable):
Under the hood, these templates are rendered using the underscore.js template()
function.
The underscore.js template()
function "compiles" the template content into a rendering function, which is then called with a data object containing the variables to be rendered.
var tplString = document.querySelector(selector).innerHTML;
var render = _.template(tplString);
var output = render(data);
return output;
More details on the template syntax can be found in the underscore.js template documentation.
Rendering array items with Alpine.js
In Alpine.js array items are rendered using the x-for
directive:
<ul class="bundle items">
<template x-for="option in selectedOptions">
<li class="mb-2" x-show="option.products.length">
<span class="text-base font-semibold" x-html="option.label"></span>
<template x-for="product in option.products">
<div><span x-html="product.qty"></span> x <span x-html="product.name"></span></div>
</template>
</li>
</template>
</ul>
As you can see in the example above, x-for
directives can be nested.
Finally, a note straight from the Alpine.js documentation:
If you want to access the current index of the iteration, use the following syntax:
<template x-for="(product, index) in products" :key="index">
<span :class="{
'bg-opacity-100': active === index,
'hidden': (pageSize !== 1 && !!(index % pageSize))
}"
@click="getSlider().scrollLeft =
(getSlider().scrollWidth / products.length) * index; active=index;">
</span>
</template>
More details can be found in the Alpine.js x-for
documentation.