DEV Community

Dave Cranwell
Dave Cranwell

Posted on

Template Literal expressions within the Template tag seem like a missed opportunity

Template Literals are amazing, but I've lately found they make everything look like a proverbial nail, particularly when it comes to updating large blocks of HTML dynamically.

I'm still working in an environment which is mostly backend, where Perl generates HTML from templates, on top of which we add progressively enhanced javascript components.

When both your back and front end need to be able to generate common UI patterns based on a pattern library, it becomes frustrating to have to define the HTML source for each UI pattern in multiple places (once in Perl, once in JS).

The <template> tag could be useful. The backend can generate the HTML required for the component (e.g each Todo item in the Todo list) and the JS can use that HTML template to generate each new todo item.

But the only way of dynamically inserting values into that template, that I'm aware of, is with the extraordinarily clumsy use of CSS selectors in the template content. (see: https://blog.teamtreehouse.com/creating-reusable-markup-with-the-html-template-element)

Wouldn't it make so much more sense, now Template Literals are in every major browser, to add support within the <template> API for expressions? e.g

<template id="test-template">
    hello ${where}
</template>
Enter fullscreen mode Exit fullscreen mode
const tmpl = document.getElementById('test-template');

// where "MAGIC" is some means of supplying data as json 
document.body.appendChild(tmpl.content.cloneNode(true, MAGIC));
Enter fullscreen mode Exit fullscreen mode

Web Components have the <slot> system, but that requires the adoption of a much larger tech. And, yes, there's always Mustache/Handlebars et al, but again that's adding to the JS payload. Yes we also use React, but upgrading everything to React isn't always possible.

Am I alone in trying to make this work? Anyone found a framework-free or framework-lite solution for this?

Top comments (5)

Collapse
 
vonheikemen profile image
Heiker

If I understood correctly this article, I think lit-html is (close) to what you're looking for.

Collapse
 
davecranwell profile image
Dave Cranwell • Edited

Thanks, I'll give it a look. I've seen lit-html mentioned repeatedly in connection with htm in fact it was htm's latest release that got me thinking about all this. But from what I can understand htm is only usable in a preact/react environment.

At first glance I can't seem to see how to load a lit template from the DOM. My goal here is to write a JS component which contains no markup, but takes the markup it needs from the DOM. lit apparently does use <template> tags, but only as a background technique, not a primary source for rendering.

Collapse
 
vonheikemen profile image
Heiker • Edited

My goal here is to write a JS component which contains no markup, but takes the markup it needs from the DOM.

Oh I get it now. Nothing "lightweight" comes to mind.

I guess the closest thing that you could do with lit-html is evaluate the template somehow.

Don't do this at home.

<div id="app"></div>

<template id="test-template">
    hello ${data.name}
</template>

<script>
  import {html, render} from 'https://unpkg.com/lit-html?module';

  var generator = function(string) {
    var fn = new Function(
      'html',
      'data',
      `return html\`${string}\`;`
    );

    return fn.bind(null, html);
  };

  var template = document.getElementById('test-template');
  var helloComponent = generator(template.content.textContent);

  render(
    helloComponent({name: 'world'}),
    document.getElementById('app')
  );
</script>
Collapse
 
davecranwell profile image
Dave Cranwell

Just discovered the Template Instantiation spec which is essentially proposing exactly this:
github.com/w3c/webcomponents/blob/...

Collapse
 
everissimo profile image
Eduardo Veríssimo

Hi! I think what you need is eval. While it is not a full template system, I can solve most of the problems I face while making single page apps.