DEV Community

Sławomir
Sławomir

Posted on

JavaScript: Template arrays experiment

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)

Collapse
 
jwp profile image
John Peters

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.