Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Pros and cons using .insertAdjacentHTML vs .createElement
* There is a pro to using document.createElement() instead of just applying a
* string to the page that gets converted to HTML. When we use the pure string method
* we do not get a link/reference to the actual element that is seen on the page. This
* usually means we have to get the element again to modify it. For example, add an event
* listener
// .createElement() + .addEventListener()
const button = document.createElement('button');
button.innerText = 'Click me';
// We can add an eventlistener directly to the element before adding it to the page
button.addEventListener('click', function(){
console.log('I get applied to the element');
// Add it as a child of the <body>-tag
// .insertAdjacentHTML + .addEventListener()
/* In the eyes of JavaScript, this is just a pure string.
* the element created with .createElement on the other hand
* is recognized as an element. This button doesn't become a button
* until we add it to the page.
const button = `<button id="toggleMenu"> Click me</button>`;
doucument.body.insertAdjacentHTML('afterbegin', button);
* We need to get the element from the page again if we want to manipulate it
* and if we want to get the element from the page, we need to have some sort of
* identifier. In this case I added a id to easily get it from the page.
const toggleMenuButton = document.querySelector('#toggleMenu');
toggleMenuButton.addEventListener('', function(){
console.log('I am now applied to the element');
Copy link

StevenLeonCooper commented Mar 1, 2022

I had the same concern with messy click handlers but I found an elegant way to get around that. The click handler is actually dead simple, it just reads an attribute on the thing you clicked and then tries to invoke a function with that same name as a callback with the event object. You can then organize these functions however you like. Have a clickHandlers object with named properties that match them or just define them right in the JS file. Here's a sample:


  <button type="button" data-action="sayHi">
    Say Hello
  <button type="button" data-action="sayMessage" data-message="Howdy!">
    Say Howdy
  <input type="text" id="CustomMessage" size="10" placeholder="Type Here">
  <button type="button" data-action="sayCustom" data-for="#CustomMessage">
    Say a Custom Message


const clickHandlers = {};

clickHandlers.sayHi = () => {

clickHandlers.sayMessage = (src) => {
  let msg = src.dataset.message ?? "No Message!";

clickHandlers.sayCustom = (src) =>{
	let selector = src.dataset.for ?? "body";
  let text = document.querySelector(selector).value;

document.addEventListener("click", (e) => {

  let source =;
  let action = source.dataset.action;
  clickHandlers[action]?.(source, e);

That's an over-simplified version but it demonstrates how you can think about the "One Delegate to Rule them All" pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment