As Raphael hinted at, it turns out that when Magento downloads its KnockoutJS templates via an XHR (i.e. ajax) request, it also passes them through some custom parsing routines that look for a number of custom tags and attributes
This custom parsing is done by the Magento_Ui/js/lib/knockout/template/renderer
RequireJS module. This module's source code sets up a number of default tags and attributes to search for. There are also other modules which may add additional tags and attributes to this renderer. For example, the following
#File: vendor/magento/module-ui/view/base/web/js/lib/knockout/bindings/scope.js
renderer
.addNode('scope')
.addAttribute('scope', {
name: 'ko-scope'
});
will will add the <scope/>
tag and scope
attribute (<div scope="...">
) to the list of parseable attributes.
Is seems like the basic idea is to translate these tags and attributes into native Knockout "tagless" template blocks. For example, the following Magento KnockoutJS template
<each args="data: elems, as: 'element'">
<render if="hasTemplate()"/>
</each>
Translates into the following native KnockoutJS code
<!-- ko foreach: {data: elems, as: 'element'} -->
<!-- ko if: hasTemplate() --><!-- ko template: getTemplate() --><!-- /ko --><!-- /ko -->
<!-- /ko -->
The exact rules of this translation are still unclear to me -- the code in Magento_Ui/js/lib/knockout/template/renderer
is a little indirect, and it seems like they can change from tag to tag, attribute to attribute.
I've ginned up the following code snippet that can download a Magento KnockoutJS template, and translate it into native KnockoutJS code.
jQuery.get('http://magento-2-1-0.dev/static/adminhtml/Magento/backend/en_US/Magento_Ui/templates/collection.html', function(result){
var renderer = requirejs('Magento_Ui/js/lib/knockout/template/renderer')
var fragment = document.createDocumentFragment();
$(fragment).append(result);
//fragment is passed by reference, modified
renderer.normalize(fragment);
var string = new XMLSerializer().serializeToString(fragment);
console.log(string);
})
As to why Magento might do this -- my guess is wanting some sort of syntax highlighting and readability for KnockoutJS's commenting template, but never rule out more Mallory-ish reasons.
This error is returned if you do not have permissions and/or static content is not generated.
You have to run the commands
php bin/magento cache:clean && php bin/magento cache:flush
and
php bin/magento setup:static-content:deploy
and make sure the permissions (777) are ok on /pub/static/frontend
, the command of permission is:
chmod -Rf 777 pub/static/frontend
Yesterday was released a new release of Pearl theme, you can update the theme.
Best Answer
A JS component is a RequireJS module.
Magento will load these based on JSON given in custom script tags or data-* attributes. The crucial difference is that this module has to return a function. This function will be called with two arguments: the configuration object passed via the JSON, and the element (singular, non-jQuery object) that the component is called on. It is called once per matched element.
Edit: Is this a Magento thing?
This pattern is not specific to Magento. Instead, it comes from jQuery UI widgets. At their core, after all the configuration, they essentially boil down to a function that takes configuration as its first argument, and an element as its second. To see an example of this, look at the
collapsible
widget. It builds itself as a jQuery plugin, then returns the constructor at the end. If you inspect this function, you'll see the same argument order. Magento hijacked this pattern so that it can use jQuery UI.