Integrating Polymer 3 Components on Angular 5, more simple…

Jorge Antonio Gómez Colombat
5 min readApr 23, 2018

--

Intergrating Polymer and Angular

Recently published an article about my experiments with Angular, Origami and Polymer 3, but it was not until few days ago that I understood a comment by Andrew Mitchell -author of Origami- a little better about not having to use the patch-cli for patch the Angular CLI for integration with Polymer 3, -he was on the correct way-. The starter project of Vaadin for Angular not patch the Angular CLI and use Polymer 3.

Reviewing the starter project of Vaadin for Angular (Vaadin-Angular) and my previous experiences in the integration I found some steps that differ with the previous integration solution:

  1. Vaadin-Angular project´s not include the webcomponents polyfills on the index.html -like Origami- else on polyfills.ts -like does Rob Dodson and Stephen Fluin in “Using Web Components in Angular”-.
  2. Vaadin-Angular project´s team use webcomponents-sd-ce.js not webcomponents-loader.js, this last more convenient because is used for load appropriated polyfills by browser, if were necessary.

Keeping these things in mind I made some changes on my test integration project and verified that, if I use the webcomponents-loader.js in polyfills.ts thrown error on Firefox because not are loaded the appropriated polyfills, in Chrome work because not need polyfills. On other hand, if I include the webcomponents-loader.js on index.html and previously move on runtime webcomponents-loader.js to Angular app root folder (src), its work.

In this sense, the proposed solution could be:

Load a certain polyfill for all browsers adding it to the polyfills.ts

Or

Modify the angular-cli.json for move in runtime the polyfills to the src and include the webcomponents-loader.js on index.html.

On other test, that second solution not work on Firefox, if Angular application is served with ng serve --prod. Work with command for production, if use the command ng serve --prod --aot false, other valid point for first solution despite of the load needless the polyfills for some browser as Chrome.

Updated June 8th, 2018

Note: The test above was realized with @webcomponents/webcomponentsjs@1.1.0 . Recently realized this test with version 2.0.0 and the web components was charged and working appropriately using ng serve --prod. Although the Origami’s directives like ironControl related with form’s directives like[(ngModel)] not work. This, may be, could are related with the asynchronous charge of the polyfills.

The steps to achieve integration are quite similar to those specified in Origami and are describe below.

Integration

Analyzing the above elements the example of integration will be like:

Create an Angular CLI Project

Note: I proove this the example with Angular CLI 1.7.3 and 1.7.4

ng new [project-name]

Install Origami and WebComponents Polyfills

npm i --save @codebakery/origami @webcomponents/webcomponentsjs

Load the polyfills

In this step, you have two variants, you should use one or other:

  • Load a certain polyfill for all browsers

Add in src/polyfills.ts the following line:

src/polyfills.ts

/** Polyfill required for web components **/import '@webcomponents/webcomponentsjs/webcomponents-sd-ce.js';

Updated June 8th, 2018

Note: If use @webcomponents/webcomponentsjs@2.0.0, instead of webcomponents-sd-ce.js you must use webcomponents-bundle.js

  • Move in runtime the polyfills under app root and include the webcomponents-loader.js on index.html.

Note: Remember this variant has trouble generating the Angular project for production with the current stable CLI.

Add the following line to assets array on the .agular-cli.json:

.angular-cli.json

{"glob": "web*.js", "input": "../node_modules/@webcomponents/webcomponentsjs", "output": "./wc_polyfills/"}

Updated June 8th, 2018

Note: If use @webcomponents/webcomponentsjs@2.0.0, must add this other line to assets array:

{"glob": "web*.js", "input": "../node_modules/@webcomponents/webcomponentsjs/bundles", "output": "./wc_polyfills/bundles/"

In addition, add this line to the head of index.html

src/index.html

<script src="wc_polyfills/webcomponents-loader.js"></script>

Other steps are the same that are described in previous article from this point

Wait to bootstrap Angular until the polyfills are loaded

Modify your main.ts and wait for the polyfills.

main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { webcomponentsReady } from '@codebakery/origami';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
webcomponentsReady().then(() => {
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
});

Import Origami

Import Origami into your topmost root NgModule. In any modules where you use Custom Elements, add CUSTOM_ELEMENTS_SCHEMA to the module. This prevents the Angular compiler from emitting errors on unknown element tags.

app.module.ts

import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { PolymerModule } from '@codebakery/origami';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule,
FormsModule, // Origami requires the Angular Forms module
PolymerModule.forRoot() // Do not call .forRoot() when importing in child modules
],
declarations: [
AppComponent
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent]
})
export class AppModule { }

Install and use custom elements

Install elements! Persist them to package.json with the --save flag.

npm install --save @polymer/paper-checkbox@nextnpm install --save @polymer/paper-input@next

Note: The polymer components have the suffix @next, this is necessary for now because Polymer is still on preview.

Next, import the element in the Angular component that you want to use it in. Add the [ironControl] directive to elements that use Angular form directives.

app.components.ts

import { Component } from '@angular/core';import '@polymer/paper-checkbox/paper-checkbox';
import '@polymer/paper-input/paper-input';
@Component({
selector: 'app-root',
template: `
<paper-input label="Hello from Polymer" ironControl [(ngModel)]="value"></paper-input>
<paper-checkbox [checked]="checked" (checked-changed)="checked = $event.detail.value"></paper-checkbox>`
})
export class AppComponent {
value: string;
checked: boolean;
}

Run the application

Inside the Angular project execute the command ng serve and validate that it work.

Good coding!!!

--

--