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(`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.