Angular Element: Use Angular components outside the Angular
By: S M Asad Rahman
Tags: Angular, Web Components, Front End Development, JavaScript, Micro Frontends

Teaser:

We all are familiar with components: the most powerful building block in the Angular ecosystem. Components are where the Dom gets rendered, services get injected, views get re-rendered with change detection. Components can take values as inputs and trigger events as outputs. But the problem is, this beautiful block so far works only inside an Angular ecosystem. I wish we could help humanity by using angular components even outside the angular ecosystem.

Yes! From Angular 7, Angular brings the feature “Angular Element”. Now an angular component can be exported as a standalone web component. We can use it exactly like a typical HTML tag like div or span, in any HTML page, CMS or even inside a React or Vue.js project.

How it works:

Web Component is a web standard to define a new custom HTML element in the browser. Browsers maintain a registry called customElementRegistry . Using the method CustomElementRegistry.define() we can register a “dom string” and a class that defines its behavior.

Angular’s @angular/elements package exposes the method createCustomElement which converts angular component and its dependencies as a class compatible as a web component.

Currently, web standard is supported by All Chrome, Firefox, Safari and Opera browsers. We can also make it workable in other browsers using polyfills.

Use Cases:

There are at least 3 use cases where we can make use of exportable fully functional angular components as web components:

Micro front end

Legacy code migration

Plug & play web components for third-party services

Micro front end:

Like micro-service, there is another similar concept called micro-frontend. In a micro-frontend architecture, a small full-stack team is responsible to deliver not only the APIs but also their corresponding front-end components. For example, the “product team” will create product APIs and all product-related views used in different category pages, product detail page, cart & checkout page. In a case like this, all team will provide different web components and one front end team will only glue those components together in different pages.

Migration:

Projects written in Angular 1.x, Migration to Angular always has been a challenge. There is no easy magic spell-like ng update. The same is true for a case where someone wants to migrate their project to Angular from React or Vue. Web components is the best fit here. They can gradually convert their existing components/controllers to Angular web components and replace them from the existing system. Once all components/controllers are converted they can just replace the legacy system with the latest angular.

Third-party services:

Service providers can provide plug & play web components to be glued in their client’s website without any further engineering needed.

So seems it is promising if we can actually ship an angular component as a web component. So let’s make our hands dirty with the actual coding.

Example project:

Here is an example code we write a my-todo-list web component. FYI you can check the entire code here in Github.

Step 1: Write the component and service

A TodoList component to show a list of todos.

A TodoService to fetch todo’s from placeholder JSON API.

The TodoList component will take “name” as input.

TodoList component will trigger the onTodoComplete event when any todo will be marked as done.

Step 2: Tweak app.modules to export todo-list component

Since the project will be used only to export angular modules as a web component we do not need bootstrapping through the app component.

We have to declare our exportable todo-list component as entry components.

Install @angular/elements package.

Inside ngDoBootstrap hook we use createCustomElement method to compile our TodoList component as a standard web component.

hook we use method to compile our TodoList component as a standard web component. TodoList component has dependency on TodoService. Since it will be used outside the angular ecosystem, we need to pass the Dependency Injector manually so that it can load dependencies.

Step 3: Bundling

Now if we run build — files will be generated in “dist” folder. Since we want to use this in another ecosystem better to concat the files as one output file. So add these commands in package.json script section:-



"concat-es5": "concat -o output/output-es5.js ./dist/example-ng-element/runtime-es5.js ./dist/example-ng-element/polyfills-es5.js ./dist/example-ng-element/scripts.js ./dist/example-ng-element/main-es5.js", "concat-es2015": "concat -o output/output-es2015.js ./dist/example-ng-element/runtime-es2015.js ./dist/example-ng-element/polyfills-es2015.js ./dist/example-ng-element/scripts.js ./dist/example-ng-element/main-es2015.js", "concat": "npm run concat-es5 && npm run concat-es2015", "build": "ng build --prod --output-hashing=none && npm run concat",

Now if we run the command npm run build two separate files output-es5.js and output-es2015.js will be generated inside the output folder.

Step 4: Use as a web component

Now all is set. We can use these output files as our standalone web component like this:-

If we run this HTML page, we can see the todo list will be fetched and showed.

We passed the name as input, we can see the name inside the web component — which means component’s input, change detection are working!

Once we check/uncheck any todo, event-triggered and todo data will be logged in the console. So the output event is working as well!

So, like this, we can use an angular component in any other project. You can try yourself cloning the code from Github.

Ref:

Feel free to make your comment here or catch me on twitter @asad_rahman.

Visit our website to learn more about us:

www.monstar-lab.co.bd