A Brief Introduction to Angular Elements

Posted By Satwinder Singh | 04-Dec-2018

What are angular elements?

Angular elements are the feature of the angular framework that allows us to turn normal angular components which we use in our angular app into native web components. Web components are basically custom HTML elements and they are part of the DOM or the javascript API which means they are not related to angular and we can use them in vanilla javascript or in apps built with other frameworks. So angular provides us a way to create such web components.

 

What is the need of web components inside an angular app?

The obvious question which comes in mind after knowing about the web components is that why would we build web components at all? What is the use of angular elements inside an angular app? And the answer is they are useful for loading dynamic content. So let’s say we have a content management system on our backend on the server and there, our editors can create HTML code and therefore they create the content that gets loaded into our angular app in HTML. Now so far that is fine but what if we actually want to enable them to also use some of our angular components in the HTML code they prepare. If they do that which means if they use our angular component’s selector and then we load this content dynamically in our angular app, it will actually not work because our angular app is compiled ahead of time or even with just in time compilation, it is compiled before the content is loaded. So if the content contains such tags representing angular components it will not work. The reason for this is that angular doesn’t compile this code and angular elements fix this issue. It allows us to basically take our angular component and put it into a totally encapsulated self-bootstrapping HTML element which we can dump into our angular app.

 

How to use angular elements?

Now to create such a component which can be rendered dynamically as an HTML element we need to use angular elements. Angular provides us a createCustomElement method using which we can convert our normal angular components into web components which can be then rendered dynamically. Before using it we have to make sure that we have installed angular elements package using this "npm install –save @angular/elements" command just in case this isn’t installed already. Now to demonstrate this we will first create an alert-component which will be a normal angular component used to display some kind of message and then we will render this component dynamically in our app-component by converting the alert-component into a custom angular element. So our alert.component.ts file would look like this:-

 

import {Component, Input } from @angular/core;

@Component({
     selector : ‘app-alert’ ,
     template: ‘<div>This is an alert. {{message}}</div>’,
     styles: [`
         div{
             border:1px soild black;
             background: salmon;
             padding: 10px;
             font-family: sans-serif;
         }
     `]
})

export class AlertComponent{
     @Input message : string ;
}

 

Now in the app.component.ts file we have a “content” property which is initially null and in the template of this file we have a div and in this div, we use the innerHTML property binding to bind to the content. Now in the app.component.ts file, we will use the createCustomElement() method which is imported from ‘@angular/elements’ to create our custom element which thereafter will be rendered dynamically. In the constructor of the app.component.ts file we will create a new element named AlertElement which is stored in a const and we will use the createCustomElement() method in which we will pass the component as the parameter. Also, provide the import for the component at the top. Now createCustomElement() method also requires a second argument which is used to configure this element and there we need to pass the injector we are using. As we know angular uses dependency injection and the injector is the tool which does this injection and we provide it to this custom element so that the element behind the scenes is able to connect itself to our app. Therefore, we simply inject the injector in our constructor pass the key-value pairs for the injector we are injecting in the createCustomElement() method's second argument. So with this, we created a custom element and this indeed is already a native web component. Now we can use the custom web API and it should be noted that it is not an angular feature and this is a feature provided by the javascript API and call define(). This allows us to register a custom web component. In the define() method we have to pass the selector with which we want to recognize our custom component and the second parameter our newly created custom element i.e. “AlertElement”. With this, we can use our custom created element inside a setTimeout() just to give a feel that the content is loading from an asynchronous call. We also need to provide the “AlertComponent” on the entryComponents array in the app module and entryComponents is essentially an array of components which we don’t use by its selector or via routing but where you want to tell angular that we are eventually going to use it.

app.component.html file:-

<div [innerHTML]= “content”></div>

app.component.ts file:-

 

import { Component , Injector } from ‘@angular/core’;
import { createCustomElement } from ‘@angular/elements’;

import {AlertComponent} from ‘./alert.component’;

@Component({
     selector: ‘app-root’,
     templateUrl: ‘./app.component.html’,
     stylesUrls : [‘./app.component.css’]
})

export class AppComponent{
     content: null;

     constructor(injector : Injector){
         const AlertElement = createCustomElement(AlertComponent , {injector: injector});
         customElements.define(‘my-alert’ , AlertElement);

         setTimeout(() => {
             this.content = “<my-alert message="Rendered"></my-alert>”
         },1000);
     }
}

 

app.module.ts file:-

 

import { BrowserModule } from ‘@angular/platform-browser’;
import { NgModule } from ‘@angular/core’;

import { AppComponnet } from ‘./app.component’;
import { AlertComponnet } from ‘./alert.component’;

@NgModule({
     declarations: [
         AppComponent,
         AlertComponent
     ],
     imports: [
         BrowserModule
     ],
     providers: [],
     bootstrap: [AppComponent],
     entryComponents: [AlertComponent]
})

export class AppModule{ }

 

Request for Proposal

Recaptcha is required.

Sending message..