I had a fella write in to me the other day. He had some HTML, CSS, and JavaScript, and it just wasn’t behaving like he thought it ought to. The HTML had some placeholders in it and the JavaScript had some data in it, and the assumption was that the data would fill the placeholders.
To those of us with some degree of web knowledge, we can look at this and see why it’s not working like he thought it would. But I think it’s also valuable to try to see things from that perspective and then look at solutions that are hopefully as simple as the original problem seems to be.
The HTML was something like this…
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<link rel="stylesheet" href="test.css">
<script src="data.js"></script>
</head>
<body>
<section>
<div>{company_name}</div>
</section>
</body>
</html>
The JavaScript was like this…
var company_data = {
"{company_name}" : "SOME COMPANY",
};
There is nothing invalid going on here.
That’s all perfectly valid code. It is linked up right. It will run. It just doesn’t do anything besides render {company_name}
to the screen. The expectation is that it would render SOME COMPANY to the screen instead, replacing the {company_name}
placeholder with the data from the JavaScript file.
Let’s fix it with a one-liner.
In this exact scenario, to display the correct company name, we need to select that element in the DOM and replace its content with our data. We could do that by adding this one extra line to the JavaScript:
var company_data = {
"{company_name}": "SOME COMPANY"
};
document.querySelector("div").innerHTML = company_data["{company_name}"];
That’s not particularly re-usable or resiliant, but hey, it’s also not over-thinking or over-tooling it.
The expectation was templating
I think we can see at this point that what he hoped would happen is that this sort of templating would automatically happen. Provide an object with keys that match what is in the HTML, the content in that HTML is automatically swapped out. It just doesn’t work that way with raw web technologies.
No joke, there are hundreds of ways to go about handling this. Here’s a few off the top of my head:
- Use a templating language like Handlebars or Mustache
- Use a static site generator like Eleventy, which uses Liquid by default
- Make an HTML
<template>
and write your own script to use it - Make a Web Component
- Use a back-end language instead, or a language like Nunjucks to process ahead of time
- Use a preprocessor like Pug
As a general preference, I’d say doing the templating server-side or during a build is ideal — why mess with the DOM if you don’t need to?
But just to ignore that advice for a second, here’s an example of doing it client-side with Handlebars, just so the fella from the original email has a working example of how that can work:
Wouldn’t the easiest solution to be have an (unique) ID like:
Then look for the id and fill the innerHTML with stuff in the JavaScript?
I think this is an emergent issue in the complexity of web technologies. It’s unlikely that a newcomer will start with the basic building blocks in the same order that an old-timer (like you or I) would; HTML, then CSS, then JavaScript, then js snippets, frameworks etc.
Since the surface area of knowledge on the internet is so insanely vast, a newcomers first impression may be React / Vue / svelte / anything. The templating issue is a great example of reality vs. expectation.
@David King: Thanks for making your comment. Your remarks capture the salient point precisely and succinctly, which I admire.
Two thoughts:
1. Is “emergent” accurate?
2. Is this issue confined to the complexity of “web technologies”?
Reflecting on my own experience, I think the barrier of entry is quantum leaps lower now, and the opportunities to learn things in the right order still abound (HTML Goodies, MDN, You Don’t Know JS, for example.)
This was an issue for me when I started 23 years ago, but there was no Google, YouTube, StackOverflow, Quota, etc. full of people explaining how to go about things.
Also the data.js script needs to be right above the Tag or else
document.querySelector("div")
returns null, because the element does not exist at that point.
Never heard of eleventy or the html template tag. Thanks for the tip, i’m going to read into it :)
right above the
</body>
tag *Nice and informative thanks for share.
At the risk of missing the point (no doubt the original use case was more complicated that what was shown), I do think it’s fair to say that sometimes it’s alright to just write HTML
I would say,
.textContent
would be a better option than.innerHTML
from security and performance standpoints.Somehow you did for any beginner everything harder when using more abstract names in handlebars (as
source
,context
, eventemplate
orhtml
– or the likes), not to say that you treated them with ‘const’ instead of ‘var’ :).Maybe it’s just me having a problem with the naming convention, however that can really break the learning curve to a mere beginner.
Let me explain you why:
– first of all, one good solution would be to indeed use a one liner but using something much more simple and intuitive, as is jQuery for example, something that to introduce slowly the noobs to the concept of getter and setter [ get the value then set the display of data ]. Having said that, it’s obvious that the actual thing named
source
ISN’T the innerHTML – as that thing is in fact the destination of the data not it’sfountain
. The innerHTML is waitingthirsty
for data, even from various sources, if possible, so he’s quite the consumer of data, the place where everything ends.That jQuery liner could be
much intuitive than using the ugly camelCase named querySelector (again a horrible choice of naming for something that actually doesn’t
select some query
but an item, right?…)I spare you everyone here of writing the jQuery line because the issue isn’t about writing code here but about simplicity in designing the coding approach – also because the readers here are way higher than the noobs.
– once in a time Beatles told people All we need is love. In coding, all we need are good names – in order to make a language more approachable and readable, too. I look at the lesson teached to us by the most humble (and not even a programming language in itself) which is the very html :) Despite of not handling such complexities as JavaScript for example, it came with the genius idea of making things
semantic
in order to save everyone from bad idioms. Can we use semantic in this case? Yes, we can.– another horrible naming thing is using
template
for something coming from a method – a method is a function in itself – and saving it in a container – a variable. Again, maybe too much for a beginner taste :)Saying ‘const template =…’ somehow prepares the reader to look carefully to find there any specific pattern, right? Because template is like a pattern, after all, having a precise shape or a fabric of some sort ! And instead he sees there a Nothing, only an empty word, actually kind of a reference ( compile something, ok? ) which means ‘go somewhere and process something’, so (jokingly) maybe along the way you maybe will understand what happens there. Like saying
The taste of pie is known only after you eat it
:D … No real template there, nothing, only a call to action (compile a buzz or barr)…Should I continue? The
context
word is again, misused here. I’d better name it insteadorigin
because it refers to just a mere set of data, nothing much more important. Origin means also something fresh and useful – as are the data we might use from various sources (backend, an API, you name it). By contrary, acontext
is usually the space wherethings happen
, the joyful neighborhood where thechild
data ‘grow’ to adult and final use – so it’s NOT the data themselves :(.Last line aggravates everything: instead of calling its name
result
it is namedhtml
. And the horrible things keep happening (the noob sees again horrified that the thing calledtemplate
is a function, not a variable – and not even a variable, as time it is called “const” just in the previous line…)Don’t get me wrong, I love what Handlebars does, however I was against their idiotic way of naming things since the beginning, when sawing in Postman how they really rule there :D
Change the n-a-m-e-s and, yes, you will see the real beauty & power of cOdE. KISS :) (keep it simple, stupid) – for noobs, or YAGNI for extreme performance programmers ;)
Thanks.
PS writing this comment on my mobile phone, it was a burden to me to rewrite the above JS code with those own naming suggestions above, so pls everyone feel free to do it for you on your own computer. Definitely it would taste better. :) I wish / hope / this topic would raise a healthy debate about the real core programming. Thanks again to the host of the discussion! I appreciate your work
What Michael Jackson discovered when we was working on Mustache is that templates always end up trying to recreate javascript and forcing your users to learn a new syntax. https://twitter.com/mjackson/status/803808828634472448
JSX is great because it allows you to write template-like syntax with javascript, but the main issue with it is it forces you to use a lot of awkward patterns like short circuiting.
I personally think it’d ideally work more like PHP templates where you can write your logic code in native JS and insert HTML in between those blocks. No frameworks, just javascript and html.
Alpine.js is pretty nifty. It’s inline JavaScript and the syntax is modeled after vue.js, but without using a shadow DOM. Templating would be pretty simple with:
Good suggestion to do the templating server-side if possible. In this scenario, you can try Hypertag (http://hypertag.io/), a Python-inspired language for document generation, with clean indentation-based syntax and many advanced features: native custom tags, DOM manipulation, compound expressions… Quick Start: https://github.com/mwojnars/hypertag