Creating Web Components with Angular

John Au-Yeung
Apr 2 · 3 min read
Photo by Boris Smokrovic on Unsplash

Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.

In this article, we’ll look at how to create Angular Elements, which are packaged as Web Components.

Angular Elements

Web Components are supported by most browsers like Chrome, Firefox, Opera or Safari.

We can transform Angular components to Web Components to make all the Angular infrastructure available to the browser.

Features like data-binding and other Angular functionalities are mapped to their HTML equivalents.

Creating and Using Custom Elements

We can create a Web Component by creating an Angular component, then building it into a Web Component.

To create a Web Component with Angular, we have to do a few things.

First, we create a component to build into Web Components. Then we have to set the component we created as the entry point.

Then we can add it to the DOM.

We’ll make a custom component to get a joke. To do this, we first run:

ng g component customJoke
ng g service joke

to create our component and service to get our joke and display it.

Then we run:

ng add @angular/element

to add the Angular Element files to create our Web Component.

Then injoke.service.ts , we add:

import { Injectable } from '@angular/core';@Injectable({
providedIn: 'root'
export class JokeService {
constructor() { } async getJokeById(id: number) {
const response = await fetch(`${id}`)
const joke = await response.json();
return joke;

The code above gets a joke from the Chuck Norris API by ID.

Next, we write our component code as follows:

app.module.ts :

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { AppComponent } from './app.component';
import { CustomJokeComponent } from './custom-joke/custom-joke.component';
import { JokeService } from './joke.service';
declarations: [
imports: [
providers: [JokeService],
bootstrap: [AppComponent],
entryComponents: [CustomJokeComponent]
export class AppModule {

In AppModule , we add CustomJokeComponent to entryComponents so that it’ll be the entry point component instead of AppComponent .

It’ll load when custom-joke element is created.

app.component.ts :

import { Component, Injector } from '@angular/core';
import { createCustomElement, WithProperties, NgElement } from '@angular/elements';
import { CustomJokeComponent } from './custom-joke/custom-joke.component';
selector: 'app-root',
template: ''
export class AppComponent {
constructor(injector: Injector) {
const JokeElement = createCustomElement(CustomJokeComponent, { injector });
customElements.define('custom-joke', JokeElement);
showAsElement(id: number) {
const jokeEl: WithProperties<CustomJokeComponent> = document.createElement('custom-joke') as any; = id;
document.body.appendChild(jokeEl as any);

The code in the constructor creates the custom component and attaches it to the DOM with our showAsElement method.

createCustomElement is from our @angular/element code.

The showAsElement method loads our custom-joke Web Component that we defined earlier.

custom-joke.component.ts :

import { Component, OnInit, ViewEncapsulation, Input } from '@angular/core';
import { JokeService } from '../joke.service';
selector: 'custom-joke',
template: `<p>{{joke?.value?.joke}}</p>`,
styles: [`p { font-size: 20px }`],
encapsulation: ViewEncapsulation.Native
export class CustomJokeComponent implements OnInit {
@Input() id: number = 1;
joke: any = {};
constructor(private jokeService: JokeService) { } async ngOnInit() {
this.joke = await this.jokeService.getJokeById(

We put everything in one file so they can all be included in our custom-joke Web Component.

The @Input will be converted to an attribute that we can pass a number into and get the joke by its ID.

We leave custom-joke.component.html and app.component.html blank.

Photo by David Clode on Unsplash


We use the @angular/element package to create a Web Component that we can use.

The difference is that we include the template and styles inline.

Also, we have to register the component and attach it to the DOM.

A note from JavaScript In Plain English: We are always interested in helping to promote quality content. If you have an article that you would like to submit to JavaScript In Plain English, send us an email at with your Medium username and we will get you added as a writer.

JavaScript In Plain English

New articles every day.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store