The most popular intro says that I can easily clone html templates within my document.
<template id="mytemplate">
<img src="" alt="great image">
<div class="ment"></div>
</template>
The word "template" however implies that you won't copy-paste it as is, unmodified. Template means that you want to update some variables with specific values. It remends the following approach for updating the node:
var t = document.querySelector('#mytemplate');
// Populate the src at runtime.
t.content.querySelector('img').src = 'logo.png';
var clone = document.importNode(t.content, true);
document.body.appendChild(clone);
Isn't it perfect? There is querySelector to get the element so that you can update its attributes. I just do not understand why does he updates the template before cloning it. But that is not my question. The real question is that, in mine case, the location of variable to update is unknown. It can be either attribute or innerText in whatever template structure is. This is the most general and frequent use of template, I believe. So, I can ensure that the variable id is unique within the template, like #reply here
<template id="ment-template">
<li class="ment">
<div class="ment-author"></div>
<div class="ment-body"></div>
<div class="ment-actions">
<a href="#reply" class="reply">Reply</a>
</div>
</li>
</template>
ought to update the #reply
, but author does not explain how to do that. I succeeded to use innerHTML on the original template, document.querySelector('#mytemplate').innerHTML.replace(id, value)
but this breaks the template for later use, as explained above. I failed to update the cloned text. This is probably because template.clone produces a document fragment, which has no innerHTML. But, before pushing that forth, I decided to investigate for alternatives since I know that innerHTML/outerHTML is not quite standard.
Alternative for innerHTML? inspects the alternatives to innerHTML but again, they assume too much about the template. Instead of just replacing some specific identifiers with user values, they pletely recreate the template, which defeats the whole notion of template. Template looses any sense once you recreate its whole code in the variable valuation. So, how is <template>
is supposed to use?
The most popular intro says that I can easily clone html templates within my document.
<template id="mytemplate">
<img src="" alt="great image">
<div class="ment"></div>
</template>
The word "template" however implies that you won't copy-paste it as is, unmodified. Template means that you want to update some variables with specific values. It remends the following approach for updating the node:
var t = document.querySelector('#mytemplate');
// Populate the src at runtime.
t.content.querySelector('img').src = 'logo.png';
var clone = document.importNode(t.content, true);
document.body.appendChild(clone);
Isn't it perfect? There is querySelector to get the element so that you can update its attributes. I just do not understand why does he updates the template before cloning it. But that is not my question. The real question is that, in mine case, the location of variable to update is unknown. It can be either attribute or innerText in whatever template structure is. This is the most general and frequent use of template, I believe. So, I can ensure that the variable id is unique within the template, like #reply here
<template id="ment-template">
<li class="ment">
<div class="ment-author"></div>
<div class="ment-body"></div>
<div class="ment-actions">
<a href="#reply" class="reply">Reply</a>
</div>
</li>
</template>
ought to update the #reply
, but author does not explain how to do that. I succeeded to use innerHTML on the original template, document.querySelector('#mytemplate').innerHTML.replace(id, value)
but this breaks the template for later use, as explained above. I failed to update the cloned text. This is probably because template.clone produces a document fragment, which has no innerHTML. But, before pushing that forth, I decided to investigate for alternatives since I know that innerHTML/outerHTML is not quite standard.
Alternative for innerHTML? inspects the alternatives to innerHTML but again, they assume too much about the template. Instead of just replacing some specific identifiers with user values, they pletely recreate the template, which defeats the whole notion of template. Template looses any sense once you recreate its whole code in the variable valuation. So, how is <template>
is supposed to use?
2 Answers
Reset to default 4Here is mine solution, the valuate
function
<div id="div1">env: </div>
<template id="template1">
<a href="#ref">var1=var2</a>
</template>
<script language="javascript">
function valuate(template, targetParent, dict) {
var t = document.querySelector('#' + template);
var clone = t.cloneNode(true)
for (key in dict) {
clone.innerHTML = clone.innerHTML.replace(key, dict[key])
}
var fragment = document.importNode(clone.content, true)
var canvas = document.querySelector('#' + targetParent);
canvas.appendChild(fragment);
//alert(canvas.innerHTML)
}
valuate("template1", "div1", {var1:"1+1", var2:2, "#ref":"abc"})
</script>
It takes the template, dictionary and target element. Unfortunately, it fails for SVG hierarchies. Don't you know why?
Using again <template>.querySelectorAll
to select the element and setAttribute
to change the href
value
var a = <template>.querySelectorAll("a[href='#reply']");
a[0].setAttribute("href", <url>)
This is a more generic function. It changes an attribute of the selected elements within a cloned template, of course this is very basic,
//object = the cloned template.
//selector = the selector argument which selects all nodes.
//attribute = the attribute to change.
//value = the value that needs to be set to the attribute.
function changeTemplateValues(object, selector, attribute, value)
{
elements = object.querySelectorAll(selector);
if (elements.length == 0)
{
return false; //stop executing. No elements were found.
}
else if (!attribute && !value)
{
return elements; //no attributes and values are set, return nodelist;
}
else
{
if (attribute)
{
//loop over all selected elements to change them.
for (var i = 0; i < elements.length; ++i)
{
if (attribute.match(/innerHTML|textContent|text|nodeValue/g) )
{
elements[i][attribute] = value;
}
else
{
elements[i].setAttribute(attribute, value);
}
}
}
else
{
//No attribute return false;
return false;
}
}
}