I recently built a text editor web app in vanilla Javascript, and after coding for a few hours, I quickly became tired of constantly creating DOM elements. I was creating the elements on the fly because they required dynamic IDs, Event listeners and content every time they were rendered. I quickly realized that a template system would be better for my needs and clean up my classes.

I decided to build my own templating engine which I decided to call DOMinator just for fun. I will walk through the basic steps I took and the code that I used to create this.

First I wanted to create a simple format for templates so I created a new file called templates.js in which I have a single object Templates filled with each of the templates I use. I built the templates as functions so I can pass variables to them. this is a template for my Doc Icons.

const Templates = {
  docIcon: function(obj) {
    return {
      tag: 'div',
      id: obj.id,
      classes: ['doc-icon'],
      properties: {
        title: obj.name,
        tabIndex: 0
      },
      children: [
        {
          tag: 'div',
          classes: ['doc-icon-header'],
          children: [
            { tag: 'h3', content: obj.name }
          ]
        },
        {
          tag: 'p',
          content: obj.exerp
        },
        {
          tag: 'div',
          id: 'docControls',
          classes: ['doc-controls'],
          children: [
            {
              tag: 'button',
              classes: ['doc-control'],
              id: 'moveDoc',
              children: [
                {
                  tag: 'i',
                  classes: ['fa', 'fa-folder']
                }
              ]
            },
            {
              tag: 'button',
              classes: ['doc-control'],
              id: 'deleteDoc',
              children: [
                {
                  tag: 'i',
                  classes: ['fa', 'fa-trash']
                }
              ]
            }
          ]
        }
      ]
    }
  }

As you can see, the tag, id, and classes are explicitly defined as keys for our objects, but anything else is passed in the properties key. We also have an array of children, with each child having the same format as the parent. In theory we could infinitely nest DOM elements with this format.

Once we have this simple Javascript Object format for our templates, it’s easy to build a ton of them pretty quickly, but how do we convert to HTML and add to the DOM?

I created a class called Dominator with instances representing a DOM element as an object. An instance would look very much like our template, except the dynamic values would be applied. I just use Object.assign() to essentially replicate the template.

class Dominator {
  constructor(object) {
    Object.assign(this, object)
  }
}

Next we need to figure out how to create the children. We can use a for loop to recursively create new instances of the class for the children. We then push the children into an empty initialized array, and after looping through we assign this.children to equal our array.

----
  constructor(object) {
    Object.assign(this, object)
    let childObjects = []
    if (object.children){
      for (const child of object.children) {
        let childObject = new Dominator(child)
        childObjects.push(childObject)
      }
    }
    this.children = childObjects
    this.element = this.domElement
  }
----

#html #code #dom #metaprogramming #javascript

How to Create a Javascript HTML Generator
1.20 GEEK