-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Description
Using Magento 2.1.1, as installed via composer integrator method.
The {{templateVars}} in the UI Component's xhtml rendering engine don't work as expected due to a logic error in
vendor/magento/framework/View/TemplateEngine/Xhtml/Compiler/Text.php
Steps to reproduce
- Install and enable to module located in https://github.com/astorm/magento2-simple-ui-component
- Make note of UI Component
messagedata configuration: https://github.com/astorm/magento2-simple-ui-component/blob/master/app/code/Pulsestorm/SimpleUiComponent/view/base/ui_component/etc/definition.xml#L5 - Make note of XHTML template variable
{{message}}https://github.com/astorm/magento2-simple-ui-component/blob/master/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/templates/our-new-template.xhtml#L15 - Navigate to
System -> Other Settings -> Hello Simple UI Component - View rendered XHTML template
Expected result
- The
{{message}}template variable should be replaced with the stringHello World
Actual result
- The
{{message}}variable remains unchanged.
The problem is in the text node compiler.
#File: vendor/magento/framework/View/TemplateEngine/Xhtml/Compiler/Text.php
public function compile(\DOMText $node, DataObject $processedObject)
{
$result = '';
foreach ($this->directivePool as $directive) {
$result = preg_replace_callback(
$directive->getPattern(),
function ($match) use ($directive, $processedObject) {
return $directive->execute($match, $processedObject);
},
$node->textContent
);
}
$newNode = $node->ownerDocument->createTextNode($result);
$node->parentNode->replaceChild($newNode, $node);
}
When looping through the directive pool, the original value of the $node->textContent is always used. This means, in effect, the final directive wins and the results of the earlier directives are ignored. This means if the final directive doesn't match, the original {{message}} string ends up in the text.
Compare this to the attribute compiler
#File: vendor/magento/framework/View/TemplateEngine/Xhtml/Compiler/Attribute.php
public function compile(\DOMAttr $node, DataObject $processedObject)
{
foreach ($this->directivePool as $directive) {
$node->value = preg_replace_callback(
$directive->getPattern(),
function ($match) use ($directive, $processedObject) {
return $directive->execute($match, $processedObject);
},
$node->value
);
}
}
Here the value of the node is changed each time through the loop, which is why variables in attributes are properly swapped. You can see this in core code with the {{spinner}} variable.
#File: vendor/magento//module-ui/view/base/ui_component/templates/listing/default.xhtml
<div
class="admin__data-grid-outer-wrap"
data-bind="scope: '{{getName()}}.{{getName()}}'"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../../../Ui/etc/ui_template.xsd">
<div data-role="spinner" data-component="{{getName()}}.{{getName()}}.{{spinner}}" class="admin__data-grid-loading-mask">
<div class="spinner">
<span/><span/><span/><span/><span/><span/><span/><span/>
</div>
<h1>This is a test</h1>
</div>
<!-- ko template: getTemplate() --><!-- /ko -->
</div>