DEV Community

Pascal Louwes
Pascal Louwes

Posted on • Originally published at recoveryarea.nl on

Adding DOM Elements LIKE A BOSS

In my AB testing Framework I have a method that creates DOM nodes, sets their properties and attributes, and adds them to the DOM for me. Since in 90% of all the tests we run, we need one or more custom elements, I decided to create a function that does all that for me. The requirements were:

  • create (one or more) DOM Element(s) by config
  • add attributes to element (class, style, innerText/ -HTML, and even events like onclick)
  • insert element in DOM relative to a target, or replace that target
  • return a reference to the element for later use

OK, let’s write a function that can do all of that – it’s possible to do it in only a few lines of code!


const buildNodesFromConfigArray = nodes => nodes.map(({tag, attributes, position, target}) => {
    // create the element
    const node = document.createElement(tag);
    // iterate through property list,
    // match innerText, innerHTML or event attributes (event attributes should be wrapped functions!),
    // else just set the attribute
    Object.entries(attributes).map(([key, value]) => (/^(inner|on)\w+$/i.test(key)) ? node[key] = attributes[key] : node.setAttribute(key, value));
    // [optional] place it in the DOM
    if (position && target) (position === "replace") ? target.replaceWith(node) : target.insertAdjacentElement(position, node);
    // return it for use in the caller function
    return node;
});

Enter fullscreen mode Exit fullscreen mode

As you can see, first we create a DOM element. Then comes a pretty magical line of code if I may say so, we map over the attributes object so we can check these as key-value pair, one by one. If the regex matches on the key, we have to set either innerText or innerHTML, or an event like ‘onclick’ or ‘onmousesomething’ or whatever event you fancy. If it does not, we set an attribute with name ‘key’ and value ‘value’. Finally, if a position and target are set in our config, we add the element to the DOM relative to a target, or replace that target. Now, let’s see this awesome code in action!


// let's create a new stylesheet
const [style] = buildNodesFromConfigArray([{
    tag: 'style',
    attributes: {
        id: "ra-stylesheet",
        rel: "stylesheet",
        type: "text/css"
    },
    position: "beforeend",
    target: document.head
}]);

Enter fullscreen mode Exit fullscreen mode

We declare an array and use the destructure technique to have the variable(s) immediately available to us. That way we can use it later on in our code. Like so, for instance:


style.append(document.createTextNode(`
    body {
        background-color: #00ff88;
    }
`))

Enter fullscreen mode Exit fullscreen mode

Here you can see the stylesheet added to the DOM. All the properties are set like we specified.

inspect element shows the sheet where we expect it.

What if we want to add some meta tags to the head of our site? That would look like this. (You could actually skip the variable declaration if all you want is to add these to the head).


const [meta1, meta2] = buildNodesFromConfigArray([{
    tagName: "meta",
    attributes: {
        class: "ra-133-meta",
        property: "og:type",
        content: "website"
    },
    position: "beforeend",
    target: document.head
}, {
    tagName: "meta",
    attributes: {
        class: "ra-133-meta",
        property: "og:site_name",
        content: document.location.origin
    },
    position: "beforeend",
    target: document.head
}])

Enter fullscreen mode Exit fullscreen mode

Here’s a final example, where we won’t be needing the elements later in our code, we just want them added in the DOM:


buildNodesFromConfigArray([{
    tagName: "div", //
    attributes: {
        class: "first",
        innerText: "My Paragraph",
        onclick: (event) => {
            // make sure the value here is an actual function!
            alert(event)
        }
    },
    position: "beforebegin", // use insertAdjacentElement position parameter, or replace
    target: document.querySelector("#someElement")
}, {
    tagName: "div",
    attributes: {
        class: "second",
    },
    position: "replace",
    target: document.querySelector("#someOtherElement")
}]);

Enter fullscreen mode Exit fullscreen mode

OK, now you know how to create one or more DOM elements LIKE A BOSS. Contact me if you want to know more!

Next time, I’ll share a trick I posted on Twitter a while ago, how I exclude IE from my tests, the recoveryArea way!

Happy coding 🙂

The post Adding DOM Elements LIKE A BOSS appeared first on recoveryArea.

Discussion (0)