The idea:
Use JavaScript arrays instead of template strings to render some HTML.
I created a tiny library called template arrays to show this experimental concept.
Example
Lets consider simple article template.
We need to show the following data:
- article title
- author name
- article content
- views (if more than 100, we want to add class -popular to article)
The expected result:
<article class="article -popular">
<header class="article_header">
<h2 class="article_heading">Lorem ipsum</h2>
<p class="article_author">John Doe</p>
<p class="article_views">views: 102</p>
</header>
<div class="article_content">
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Minima deserunt officia laboriosam eligendi id assumenda
veritatis ad dolore voluptatibus quas?
</div>
</article>
Requirements:
- easy way to change attributes
- easy way to add variables (text or other elements inside template)
Implementation
This could be our test article data:
const data = {
title: 'Example Title',
author: 'slavcoder',
views: 125,
content: 'lorem ipsum dolorem lorum'
}
Comparison
Implementation of simple article could look like this:
Using template string
function getArticle(data) {
const popular = data.views > 100 ? '-popular' : ''
return `
<article class="article ${popular}">
<header class="article_header">
<h2 class="article_heading">${data.title}</h2>
<p class="article_author">${data.author}</p>
<p class="article_views">views: ${data.views}</p>
</header>
<div class="article_content">
${data.content}
</div>
</article>
`
}
document.body.innerHTML += getArticle(data)
Using template arrays
import render from 'template-arrays'
const article = [
['article', {attr:'article', class:'article'}],
['header', {class:'article_header'}],
['h2', {class:'article_heading'}],{var:'title'},['/h2'],
['p', {class:'article_author'}],{var:'author'},['/p'],
['p', {class:'article_views'}],'views: ',{var:'views'},['/p'],
['/header'],
['div', {class:'article_content'}],
{var:'content'},
['/div'],
['/article']
]
document.body.innerHTML += render(article, {
attr: {
article: {
class: data.views > 100 ? '-popular' : ''
}
},
var: {
title: data.title,
author: data.author,
views: data.views,
content: data.content
}
})
Template arrays - how it works
- Add attributes in object, just after tag name:
['p', {class:'paragraph', id:'test1'}]
- To define variables, set literal with var property:
{var:'name'}
- If you want to edit some attributes later, set attr property:
['p', {attr:'name'}]
(just like other attributes above)
The render function takes two arguments: array with template and object with two following properties:
- attr (used to set or update attributes)
- var (used to add some text or other template)
const example = [
['div', {attr:'container', id:'container', class:'className1'}],
{var:'insideElement'},
{var:'insideText'},
'just text',
['/div']
]
const exampleHTML = render(example, {
attr: {
container: {
'data-info': 'data attribute example',
id: 'new-id',
class: 'className2 className3',
style: `
color: red;
display: block;
width: 250px;
`
},
spanInside: {
id: 'inside-span-id',
class: 'inside-span-class',
style: 'color: blue;'
}
},
var: {
insideElement: [
['span', {attr:'spanInside'}],
'element text ',
['/span']
],
insideText: 'simple text '
}
})
document.body.innerHTML += exampleHTML
What if you won't define attr or var in render function but used in template? It will be simply ommited, no worries.
Advantages
Even though it may look more complicated than template strings, I think it gives more clarity and flexibility.
- you can split templates to parts, just like below:
const header = [
['header', {class:'article_header'}],
['h2', {class:'article_heading'}],{var:'title'},['/h2'],
['p', {class:'article_author'}],{var:'author'},['/p'],
['p', {class:'article_views'}],'views: ',{var:'views'},['/p'],
['/header']
]
const article = [
['article', {attr:'article', class:'article'}],
... header,
['div', {class:'article_content'}],
{var:'content'},
['/div'],
['/article']
]
- you can save template arrays in .json files and still use attr and var
- you can easily change attributes in render time
- it is also pretty fast (check out my test on this example - render up to 10 000 elements)
Links
If you found it interesting, check out my repository and live example
Thanks for reading about my experiment :)
Have a nice day!
Sławomir.
Top comments (1)
Nice. The first step away from declarative html which, really is burdensome, repetitive etc. Templating is a better in every way in particular reuse and abstraction.