Creating Web Components with Angular
Tags: angular, webdev, programming, javascript
Published: 2021-01-23 00:19:07

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

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 in`joke.service.ts` , we add:

```
import { Injectable } from '@angular/core';

@Injectable({  
  providedIn: 'root'  
})  
export class JokeService { 
  constructor() { } 

  async getJokeById(id: number) {  
    const response = await fetch(`http://api.icndb.com/jokes/${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';

@NgModule({  
  declarations: [  
    CustomJokeComponent,  
    AppComponent  
  ],  
  imports: [  
    BrowserModule,  
  ],  
  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';

@Component({  
  selector: 'app-root',  
  template: ''  
})  
export class AppComponent {  
  constructor(injector: Injector) {  
    const JokeElement = createCustomElement(CustomJokeComponent, { injector });  
    customElements.define('custom-joke', JokeElement);  
    this.showAsElement(20);  
  } 

  showAsElement(id: number) {  
    const jokeEl: WithProperties<CustomJokeComponent> = document.createElement('custom-joke') as any;  
    jokeEl.id = 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';

@Component({  
  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(this.id)  
  }}
```

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.

Conclusion
==========

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.