Building Custom Elements / Web Components with Angular 6
5-step guide using Angular CLI and Angular Elements
With the newest Angular CLI (version 6, released 2018–04–03) and the new addition to Angular family — the Angular Elements package it’s extremely easy to create native custom elements.
So now, without further ado, let’s see some code!
1. Install Angular CLI 6 and initialize the project
npm i -g @angular/cli
ng new elements-demo --prefix custom
We’re not doing anything special yet, so all the normal
ng new parameters apply, you could add sass or anything to the mix, but here we’ll stop at setting a custom prefix to, well, “custom”.
2. Add elements & polyfill
In order to have elements functionality available we need the Angular library and a polyfill — with the new CLI it’s just a matter of one(!) simple command:
ng add @angular/elements
3. Create a component
Let’s create one with Input and Output to see how they translate to custom elements that are understood by browsers:
ng g component button --inline-style --inline-template -v Native
ViewEncapsulation.Native so that the styles are bundled with the template and the component’s class into one file.
After adding some style & template our
button.component.ts looks like this:
4. Registering component in NgModule
This is the vital part: we use the Angular’s
createCustomElement function to create a class that can be used with browsers’ native
Angular documentation describes this best:
createCustomElementBuilds a class that encapsulates the functionality of the provided component and uses the configuration information to provide more context to the class. Takes the component factory’s inputs and outputs to convert them to the proper custom element API and add hooks to input changes.
The configuration’s injector is the initial injector set on the class, and used by default for each created instance.This behavior can be overridden with the static property to affect all newly created instances, or as a constructor argument for one-off creations.
What is also special about this module is that, since our
ButtonComponent is not a part of any other component, and is also not a root of an Angular application, we need to specifically tell Angular to compile it: for this we put it on the
We also need to tell Angular to use this module for bootstrapping, hence the
app.module.ts should now look like this:
5. Build, optimize and run the code
To try our component out we will serve a simple html with
http-server, so let’s add it:
npm i -D http-server
In order to build we will use a standard
ng build command, but since it outputs 4 files (
main.js) and we’d like to distribute our component as a single js file, we need to turn hashing file names off to know what are the names of files to manually concatenate in a moment. Let’s modify the “build” script in
package.json and add “package” and “serve” entries:
"build": "ng build --prod --output-hashing=none",
| gzip > elements.js.gz",
"serve": "http-server --gzip"
Now the sample
And let’s see this in action!
npm run build && npm run package
npm run serve
So what were the crucial things we did here? In summary we’ve:
- added elements-relared libraries with
- registered the Angular component as custom element in a module
- combined build artifacts into one file and gzipped them
Not that difficult, right? Personally, I am extremely excited that this is such an easy process — it will definitely encourage Angular devs that might have been a conservative in looking into custom elements, to just start playing with the tech, and soon, use it as a standard tool in their tool belts.
Oh, and btw. the resulting
elements.gz.js weights 62kB, which, considering that we have the full power of Angular framework inside it, is a pretty remarkable result!
As usual, you can browse the completed code on Github.
Did you learn something new? If so please:
→ clap 👏 button below️ so more people can see this
→ follow me on Twitter (@sulco) so you won’t miss future posts!