ng-India

Create cross framework Components using Angular Elements

#ngIndia

www.ng-ind.com

Feb 24, 2018

Pankaj Parkar

@pankajparkar

Pankaj Parkar

Senior Software Engineer

TSS Consultancy PVT LTD

  • Microsoft MVP
  • Daily Code in .Net and Angular
  • Stackoverflow Topuser for Angular and AngularJS
  • 100k points on Stackoverflow

Don't try this on Prod

Angular Labs

  • Schematics: Angular Dev Kit / CLI team generic tooling efforts like `ng new`, `ng generate`, etc
  • Component Dev Kit: help developers to craft solid, well-tested tools to add common interaction patterns with minimal effort like `tables` and `stepper`.
  • ABC — The ABC (Angular + Bazel + Closure)
  • Angular Elements: Use angular component cross platform

Experimental API's

Angular is ideal for building complete applications

Rob Wormald, Angular Team

But it becomes challenging for scenarios that don't fit in Single Page Application Model

Challenges

  • Reusability of code (cross platform)
  • Enhance existing application
  • Content Management System pages
  • Embed Widgets inside another application

Reusability of Code

  • Common components should be reusable across different projects
  • Cross code sharing between different teams

Enhance existing application

  • Sprinkle Angular inside any application 
  • In case of AngularJS, you should have `ng-app` which is root of application and AngularJS own that DOM
  • In case of Angular, it should have main component, who will the root component of component Tree.

Content Management System Pages

  • Configuration driven site.
  • User could drag and drop features
  • Application can have more than one root element

Use existing component as Widget

  • Use existing unit of business functionality inside another application
  • Dashboards / Mini Apps
  • The widget can be placed on any web application which is not made necessarily in Angular

Running Angular on Mixed environment

  • AngularJS
  • React
  • Polymer 
  • jQuery
  • Aurelia
  • Vue
  • Vanilla JS
  • etc..

Angular components are tough to use outside Angular

Rob Wormald, Angular Team

Why you want to use Angular outside?

Why you want to use Angular outside?

Can we use something that follow Web Standards and address our issue?

Web Component

Web Component Specs

  1. Template
  2. Shadow DOM
  3. Html Imports
  4. Custom Elements
<template>
  <h1>Hello World!</h1>
</template>

We have similar technique, that used inside `ng-template`

They can be used at runtime

Web Component Specs

  1. Template
  2. Shadow DOM
  3. Html Imports
  4. Custom Elements
<my-app>
  <#shadow-root>
    <h1 class=”title”></h1>
  </shadow-root>
</my-app>

We can do this for component using encapsulation set to Native.

Web Component Specs

  1. Template
  2. Shadow DOM
  3. Html Imports
  4. Custom Elements
<head>
   <link 
    rel="import" 
    href="my-widget.html" />
</head>

This spec is deprecated, this is not going to implement by browsers.

Html Imports

Web Component Specs

  1. Template
  2. Shadow DOM
  3. Html Imports
  4. Custom Elements
<body>
  <my-navbar></my-navbar>
  <div>
    <my-sidebar></my-sidebar>
    <my-main-content></my-main-content> 
  </div>
  <my-footer></my-footer>
</body>

Html Imports

Custom Element

  • Standard way of defining web component
  • Extend the browser vocabulary

Custom Elements

class MyDatePicker extends HTMLElement {}

window.customElements
  .define(‘my-datepicker’, MyDatePicker);

It has below native DOM objects

  1. Attributes

  2. Events

  3. Properties

  4. Method

Custom Elements - Attributes

class MyDatePicker extends HTMLElement {

  static observedAttributes = [‘current-date’];

  attributeChangedCallback(oldV, newV, key){
    //update the DOM somehow
  }
}
<my-datepicker 
  current-date=”10/10/2017”>
</my-datepicker>
const picker = document.querySelector(‘fancy-datepicker’);
picker.setAttribute(‘current-date’, new Date().toString());

Custom Elements - Properties

class MyDatePicker extends HTMLElement {

  set currentDate(value){
    //update the DOM somehow
  }

  get currentDate(){ … }  
}
const myDatePicker = document.querySelector(‘my-datepicker’);
myDatePicker.currentDate = new Date();

Custom Elements - Event

const picker = document.querySelector(‘my-datepicker’);

const onDateChange = (date) => console.log(date);
picker.addEventListener(‘date-change’, onDateChange);

Custom Elements - Method

class MyDatePicker extends HTMLElement {
  emitDateChange(){
    let dateChangeEv = 
       new CustomEvent(‘date-change’,{details});
    this.dispatchEvent(dateChangeEv);
  } 
}
const myDatePicker = document.querySelector(‘my-datepicker’);
myDatePicker.currentDate = new Date();

Custom Elements - Reactions /Lifecycle Hooks

class FancyDatePicker extends HTMLElement {

  connectedCallback(){ … }

  disconnectedCallback(){ … }

  attributeChangedCallback(oldV, newV, key){ … }

  adoptedCallback(){ … }

}

Web Component works out of the box in Angular, it supports by design

<my-angular-app>
  <my-input
    [attr.foo]=”someString”
    [someProp]=”someProp”
    (someEvent)=”doStuff()”>
   </my-input>
</my-angular-app>

Angular with Web Component

Then why not use Web Components?

Source: http://pascalprecht.github.io/slides/angular-elements/#/14

Angular API looks similar to CE

NG

CE

@HostBindings

@Input

@Output

@Lifecycle Hooks

Attributes

Properties

CustomEvent

Reactions

Angular Elements

  • Export Angular Components as custom-element that can re-usable on any application
  • Self bootstrapping
  • Follow current web standard
  • Now zone is optional since Angular version 5

Angular Component packaged as web component

Other even doing that

SkateJS

How to setup Angular elements

// app.module.ts
import { HelloWorldComponent } from './hello-world';

export const CEComponents = [HelloWorldComponent];

@NgModule({
  imports: [BrowserModule],
  declarations: CEComponents,
  //all custom-element should be here
  entryComponents: CEComponents
})
export class CustomElementsModule {
  ngDoBootstrap() {} // required in bootstrap module
}

How to setup Angular elements

// main.ts
import { registerAsCustomElements } from '@angular/elements';
import { CEComponents, CustomElementsModule } from './app';

registerAsCustomElements(CEComponents, () => {
  return platformBrowserDynamic()
    .bootstrapModule(CustomElementsModule);
}).then(_ => {
  // application code goes here
}).catch(onError);

How it look in general

<html>
  <head>
    ...
    ...
    <script src="my-customelement.bundle.js"></script>
    ...
  </head>
  <body>
    ...
    <my-ng-component></my-ng-component>
    ...
  </body>
</html>

Where is it heading?

<html>
  <head>
    ...
    ...
    <script src="angular-mini.js"></script>
    <script src="my-custom-element.bundles.js"></script>
    ...
  </head>
  <body>
    ...
    <my-ng-component></my-ng-component>
    ...
  </body>
</html>

jQuery datepicker

Jquery dialog modal example

<html>
  <head>
    ...
    ...
    <script src="jquery.js"></script>
    <script src="jquery.datepicker.js"></script>
    ...
  </head>
  <body>
    ...
    <input id="my-datepicker" />
    <script type="javascript">
       $('#my-datepicker').datePicker({
         format: 'dd-MM-yyyy'
       })
    </script>
    ...
  </body>
</html>

Demo Time

  • Angular with CE Component - Demo
  • ReactJS - Demo
  • VueJS - Demo

Future??

Angular Ivy Renderer (beta) +

Angular Elements

Don't try this on Prod

Try this at Home, it is going to be awesome in coming future

Q & A

References

  • https://blog.angular.io/the-angular-team-at-angularmix-2d56fd7fde65

  • https://github.com/angular/angular/issues/21706

  • http://slides.com/andreiantal/ng-europe_angular-elements#/33

  • http://slides.com/andreiantal/ng-europe_angular-elements#/3

  • https://github.com/andrei-antal/ng-europe-demo-angular-elements (Thanks Andrei Antal)

  • https://github.com/pankajparkar/ng-india-angular-elements-demo

  • https://github.com/pankajparkar/ng-india-vueapp

  • https://github.com/pankajparkar/ng-india-reactapp

  • https://medium.com/@ezekizibzibadze/angular-and-web-components-a-k-a-angular-elements-e009b057cd75

Create cross framework Components using Angular Elements

By Pankaj Parkar

Create cross framework Components using Angular Elements

  • 1,053