Building a Custom Element Using Angular Elements

January 20, 2018 5 min read Angular

Today, we're going to experiment with a rendering of an Angular element (which is wrapped by Web Component) inside a non-Angular project, such as React.

Update: I’ve published an up-to-date article about Angular Elements. Check it out to learn about the latest API of Angular Elements:

Keep reading this article in order to get a sense of the concept.

Preface

Two and a half months have passed since Angular Elements project was revealed at the AngularConnect conference and shocked the Angular community:

Along with a lot of excitement and expectation, it’s really important to remember that:

As of today, Angular Elements is just an experimental project of the Angular Labs.

Don’t get me wrong - this project is brilliant, without a doubt. But, you should know that it’s not ready for production purposes and either for development.

In case you’re not familiar with the Angular Labs term - it’s an idea that was announced during the AngularMix conference, in order to balance the community with new explorations - before these are released officially. In other words, it’s the place where the really cool things are started.

The logo of Angular Labs

The logo of Angular Labs

This article will examine what are the benefits of Angular Elements, through creating an experimental custom element and rendering it inside a non-Angular project, such as React.

What are Angular Elements?

Imagine that you’ve developed an awesome Angular component. However, in real life, not all the web applications are Angular-based or even single-page. You wish to use your amazing component as part of any web application in a non “hacky” way. Soon, there will be a neat way and it’ll be called - Angular Elements.

Angular Elements are ordinary Angular components, which are packaged as Custom Elements. In fact, Angular takes charge of initializing a custom element and bridging the attributes, events and lifecycle hooks between the component to that custom element.

“Angular Component on the inside, standards on the outside.” (Rob Wormald)

This approach let us develop reusable components in the way that’s familiar to us, and yet, embedding these in every kind of website (vanilla JavaScript, React, Vue, WordPress, etc. - it really doesn’t matter).

Well, are you ready to build a custom element? πŸ˜‰

Building a Custom Element

Let’s create a component to show the world how much we love the open source community:

Notice that’s an ordinary component, which displays a “Made With Love” message and receives a few parameters: the developer name, his website, a valid color format (RGB, Hex, etc.) and a size for the heart. The name attribute is mandatory, so we log an error in case it’s undefined or empty. We bind these attributes inside the appropriate template and display a non-clickable developer name when the URL isn’t provided.

The styles file is pretty straightforward, thus we won’t dive into it.

The next step is attaching the source code of @angular/element package inside our project, in order to import the registerAsCustomElements function and the other necessary files. In practice, we should avoid that way of importation. However, these files aren’t available at this time on master - so when these are merged into master, we’ll install and import them like a regular Angular package. This package is targeted to be published as part of Angular 6. Update: It’s already available on master and you should install it like a regular package. Read my new article here.

Now, we register our component with the AppModule:

In the above example, we create an array of custom elements. Also, we register its items with the declarations and entryComponents arrays. In case you didn’t know, “Entry Components” is an array of components which aren’t embedded in a particular template, but still created somehow imperatively.

As opposed to other AppModule files - we don’t register a bootstrap component with this module, because we don’t have (and need) one like that. This is why ngDoBootstrap is implemented as an empty stub as well.

Great, we’re making progress. So far, we created a component and registered it with a module - but, we haven’t done yet any distinctive thing with Angular Elements. Let’s get the hang of it!

As you know, there’s a main.ts file for each Angular application. This is used as the main entry point which bootstraps the application. As mentioned above, we don’t have a bootstrap component. However, our custom element should have a self-bootstrapping capability. So, in order to achieve that, let’s use the registerAsCustomElements function:

As you can see, we pass the customElements to that function. After the bootstrapping process finishes, it takes each component in the provided array and wraps it with the Custom Element Web API. Currently, the browsers don’t support custom elements perfectly and thus we load several polyfills.

Take a look at the final result:

Live Previews

Well, it’s about time to give our custom element a try. You should know that my blog isn’t an Angular-based (based on Hugo actually) so it’s a perfect match to render the element here:

In case you traverse the DOM of this page, you’ll notice the following usage alongside its scripts file:

As I promised you, here’s an example for a React project that renders our custom element:

Conclusion

Angular Elements will provide a way to share our components everywhere on top of custom elements (web components). We covered this new way with a brief introduction and building an embeddable Angular element.

Here are some references you’d probably like to check out: