Custom elements (web components) — register dynamically in the DOM with custom-element-register package

Chris Kitson
2 min readJan 28, 2019

I have been working quite a bit with custom elements, more specifically with Angular’s take on them with Angular Elements but that is neither here nor there for the purposes of this post.

I couldn’t find a well packaged dynamic solution to injecting script and custom elements into the DOM at runtime, yet the implementation is pretty straight forward (maybe that’s why).

Why would I want to do this?

In a world of SPAs (single page applications) it makes sense to only inject scripts as we need them. Especially if your custom element is serving as a gateway to expose much deeper layers of your stack. You don’t want the performance overhead if you don’t need it!

I’ve created a little script which does two things:

  1. Dynamically creates a <script> tag in the DOM body to inject a JavaScript file which defines a custom element.
  2. Dynamically injects a custom element tag e.g. <my-app /> into a container (HTML element) of your choice.

As I already mentioned, the implementation is pretty basic:

How can I use it ?

To utilise this in your project, follow these simple steps:

  1. Add the npm dependency to your project:
    npm i custom-element-register --save
  2. ImportRegisterCustomElement script:
    import { RegisterCustomElement } from 'custom-element-register';
  3. Call RegisterCustomElement() script when you want to load the custom element dynamically with the following properties:

container: HTML element your custom element tag should be injected into
name: a unique name which must match your custom element definition
src: path to your JS file serving your custom element

How would that work in a Angular component?

In an Angular component, it would be pretty much as mentioned above but I thought I would share an additional hook which works quite well to inject a custom element without adding any additional HTML tags to your component.

I know that DOM manipulation is naughty but I am taking this as an exception given my use-case.

Import some additional dependencies from /core:

import { ElementRef, AfterViewInit } from '@angular/core';

Implement the AfterViewInit lifecycle hook on your class definition:

export class SomeComponent implements AfterViewInit {

Create a reference to el which will be a pointer towards our component element:

constructor(private el: ElementRef) {

Now you can use RegisterCustomElement in AfterViewInit to do the magic! The thing to note here is the reference to nativeElement.

ngAfterViewInit() {
RegisterCustomElement(this.el.nativeElement, 'my-app', '/my-app/element.js');
}

Finally, here’s the Github if you are interested:

Thank you for taking the time to read my article.

--

--