The main motive of this article is to add variable interpolation into <template>
I’m not precious of the particular naming conventions used here (engine vs emitter and variables); just keen to see the interest in the idea and if it is worth implementing a mock up.
Use cases for extension:
- Removal of boilerplate template rendering code
- Defined interface for client and server side detection of template types
- Fall back should allow for simple code to make up for lack of support
Here is a sample example template:
<template id="test">
<div>
<h2 class="heading"></h2>
<div class="content"></div>
</div>
</template>
Here are three alternative implementation proposals.
Registering typed content emitters:
<template id="test" type="application/x-handlebars-template">
<div>
<h2 class="heading">{{heading}}</h2>
<div class="content">{{content}}</div>
</div>
</template>
<script>
document.registerTemplateContentEmitter('application/x-handlebars-template', function (documentFragment, context) {
let template = Handlebars.compile(source);
return template(context);
});
</script>
<script>
let statements = [
{heading: 'Shouty statement', content: 'Going somewhere'},
{heading: 'Appeasing hook', content: 'Disappointing ending'}
];
let template = document.getElementById('test');
statements.forEach(function (statement) {
document.body.appendChild(template.content.emit(statement));
});
</script>
Advantages:
- More flexibility for content producers
- Emitter types are likely to work cross site reliably due to defined names globally
- Ability to use logic supplied in template engines
- Browsers could choose to adopt native type handlers too; much like video encodings (this would likely need a fall back still)
Disadvantages
- More JavaScript required to bind the type
Add bindings element for data output:
<template id="test">
<div>
<h2 class="heading"><binding bind-key="heading" /></h2>
<div class="content"><binding bind-key="content" /></div>
</div>
</template>
<script>
let statements = [
{heading: 'Shouty statement', content: 'Going somewhere'},
{heading: 'Appeasing hook', content: 'Disappointing ending'}
];
let template = document.getElementById('test');
statements.forEach(function (statement) {
document.body.appendChild(template.content.emit(statement));
});
</script>
Advantages:
- Browsers could precompile, cache and optimise for included templates
- Interpolation of variables is simplified
- Boilerplate code for use of templates is reduced
- Native interpolation
Disadvantages:
- Adding extra complexity to HTML
- Less flexibility for using existing templating
Inline emitter declaration:
<template id="test" type="application/x-handlebars-template">
<script>
document.registerEmitter(function (documentFragment, context) {
let template = Handlebars.compile(source);
return template(context);
});
</script>
<div>
<h2 class="heading">{{heading}}</h2>
<div class="content">{{content}}</div>
</div>
</template>
<script>
let statements = [
{heading: 'Shouty statement', content: 'Going somewhere'},
{heading: 'Appeasing hook', content: 'Disappointing ending'}
];
let template = document.getElementById('test');
statements.forEach(function (statement) {
document.body.appendChild(template.content.emit(statement));
});
</script>
Advantages:
- Most flexibility per template output
- Precompilation of library code would be possible internally by browsers
Disadvantages:
- Adding in a new context based JavaScript usage in the DOM which developers will be less familiar with. Being its own document instance this should be possible.
- More boilerplate code duplicated per template which could be just based upon content type
- Type attribute would then be possible to be omitted which then means crawlers and other technologies wouldn’t get the benefit of knowing the types of engine used.
I’m interested to hearing peoples interest in this.