0

Say one has an html template like this:

<template id="template">
    <div id="A"></div>
    <div id="B"></div>
    <div id="C"></div>
    <div id="D"></div>
    <div id="E"></div>
    <div id="F"></div>
</template>

Now when one clones to add it to the DOM with JavaScript, I have not come across a "nice" way to fill in all the blanks, this seems very verbose:

const object = {A:1, B:2, C:3, D:4, E:5, F:6};
const template = document.getElementById("template")
let newThing = template.cloneNode(true);
newThing.getElementById("A").innerHTML = object.A;
newThing.getElementById("B").innerHTML = object.B;
newThing.getElementById("C").innerHTML = object.C;
newThing.getElementById("D").innerHTML = object.D;
newThing.getElementById("E").innerHTML = object.E;
newThing.getElementById("F").innerHTML = object.F;
container.appendChild(newThing);

I understand one could drop the <template> and move it all into JavaScript, but I am hesitant, because I like to keep HTML in HTML files, then you have linting in the text editor etc..

To me this is not a great solution since now the HTML is living in script files:

const newThing = `
<div>
    <div>${object.A}</div>
    <div>${object.B}</div>
    <div>${object.C}</div>
    <div>${object.D}</div>
    <div>${object.E}</div>
    <div>${object.F}</div>
</div>

Is there a better way to render a template with an object of data? I have read up on lithtml, but a whole library to do this one little thing seems like overkill.

3
  • While not a full answer to your question, the repeated additions of object data can be reduced to a simple for-in loop containing the single line: newThing.getElementById(property).innerHTML = object[property]; Commented Mar 28, 2022 at 21:53
  • @DavePritlove Thats quite a good idea, one could make the id a key to a map which maps to the value, then loop through the entries. Commented Mar 28, 2022 at 22:07
  • I'm not exactly sure what you mean - the for in loop passes each of an object's property names to the loop, so the (property) in my exampe will be read as (A) on the first loop, with the innerHTML being set to the value of property A by object[property], and so on for B, C, etc on subsequent iterations. It's a ready-to-go means of sequentially extracting key/value pairs from an object. Sorry if I've misunderstood. I'll post a snippet. Commented Mar 28, 2022 at 23:17

2 Answers 2

1

The object's key-value pairs can be used directly inside a for-in loop. This allows markup stored in an object of anylength to be assigned to an html collection where each element's ID is the same as the key value of the corresponding data object.

for (const property in object) {
newThing.getElementById(property).innerHTML = object[property];
}

In the above code, 'property' is the key name of each of the objects properties and so object[property] is a direct reference to its value.

I've used this in a working snippet below to render some arbirary html stored in an object:

const container = document.getElementById("container");

const object = {
  A:"<h2>my heading</h2>", 
  B:"<a href='https://www.google.com'>Google Search</a>", 
  C:"<p>Computing is enjoyable <i>and</i> frustrating<p>", 
  D:"<div> what\'s your name ? <input type='text'></div>", 
  E:"<p>another paragraph</p>", 
  F:"<h2>goodbye!</h2>"
}
const template = document.getElementById("template")
let newThing = template.content.cloneNode(true);

for (const property in object) {
newThing.getElementById(property).innerHTML = object[property];
}

container.appendChild(newThing);
<template id="template">
    <div id="A"></div>
    <div id="B"></div>
    <div id="C"></div>
    <div id="D"></div>
    <div id="E"></div>
    <div id="F"></div>
</template>

<div id="container"></div>

Sign up to request clarification or add additional context in comments.

Comments

0

This is one possible solution, however it is not exactly advised depending on what you are trying to do

If you'd like, you can create a template with an ID in your HTML like so:

<template id="myTemplate">
        <div>${object.A}</div>
        <div>${object.B}</div>
        <div>${object.C}</div>
        <div>${object.D}</div>
        <div>${object.E}</div>
        <div>${object.F}</div>
</div>

And then call eval inorder to parse it

eval('`' + document.getElementById("myTemplate").innerHTML + '`')

This returns the formatted code that you can then place in your document

Why shouldn't you use this?

Eval is pretty dangerous, and if used wrong someone can execute dangerous commands on behalf of your website. If this is some personal project you can use this if you'd like, but preferably not on some larger scale public use website.

2 Comments

Creative solution, but yes I agree eval is not ideal, some of the security settings/headers don't allow me to do this, but nice out the box thinking.
@run_the_race Thanks! You could also try to write your own parser with say "{{…}}" contains data you want. You could then read the value in that for example "<div>{{A}}<div>" -> "A" and call "object[value]" to replace that block. But I think you you are doing it now is probably best :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.