Create cross framework Components using

Angular Elements

@pankajparkar

Pankaj Parkar

Technical Lead

Synerzip Softech India PVT LTD

  • Microsoft MVP
  • Opensource Contributor
  • Stackoverflow Topuser for Angular and AngularJS
  • 100k points on Stackoverflow
  • .Net and Angular Developer
  • Currently working on React, GraphQL & Nodejs

@pankajparkar

Don't try this on Prod

@pankajparkar

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

@pankajparkar

Challenges

  1. Reusability of code (cross platform)

  2. Enhance existing application

  3. Content Management System pages

  4. Embed Widgets inside another app

@pankajparkar

1. Reusability of Code

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

@pankajparkar

2. 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.

@pankajparkar

3. Content Management System Pages

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

@pankajparkar

4. 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

@pankajparkar

Running Angular on Mixed environment

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

@pankajparkar

Angular components are tough to use outside Angular

Rob Wormald, Angular Team

@pankajparkar

Why you want to use Angular outside?

@pankajparkar

Why you want to use Angular outside? ctd..

@pankajparkar

Ecosystem

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

Web Component

@pankajparkar

Before moving further, lets flashback

@pankajparkar

HTML 1

HTML 2

(1990)

INPUT   FORM  SELECT

@pankajparkar

BODY   A  H2   IMG   UL   LI

(1995)

HTML 5

@pankajparkar

INPUT    FORM    SELECT

BUTTON   VIDEO   AUDIO

DIALOG   CANVAS   TEXTAREA

DATALIST   IMG   PROGRESS

Input had 8 types when it got introduced

Now input have 22 types

Unix

@pankajparkar

(1970)

ls

lpr

cat

grep

sort

chmod

echo

alias

less

more

head

who

time

find

tail

echo

kill

mkdir

pwd

ps

.
.

Do One Thing and Do It Well

Unix Philosophy

source: https://en.wikipedia.org/wiki/Unix_philosophy

  • Write programs that do one thing and do it well.
  • Write programs to work together.
  • Write programs to handle text streams, because that is a universal interface.
  • Output of one program should become input for other.

Web Component

  1. Template
  2. Shadow DOM
  3. Html Imports
  4. Custom Elements

@pankajparkar

Web Components are a set of features currently being added by the W3C to the HTML and DOM specifications that allow for the creation of reusable widgets or components in web documents and web applications.

Specs

1. Template

<div style="display: none;" id="content">
  <h1>Hello World!</h1>
  <img src="success.jpg" />
  <script> 
    //some big javascript 
  </script>
</div>
var template = docuement.getElementById('content');
var div = document.createElement('div');
div.innerHTML = template.innerHTML;
document.body.appendChild(div);

@pankajparkar

Template Equivalent

<script type="text/x-template" id="content">
  <h1>Hello World!</h1>
</div>
var template = document.getElementById('content');
var div = document.createElement('div');
div.innerHTML = template.innerHTML;
document.body.appendChild(div);

@pankajparkar

1. Template

<template id="content">
  <h1>Hello World!</h1>
  <img src="success.jpg" />
  <script> 
    //some big javascript 
  </script>
</template>
var content = document.getElementById('content');
var div = document.createElement('div');
var clone = document.importNode(template.content, true);
document.body.appendChild(div);

@pankajparkar

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

2. Shadow DOM

<body>
  <div>
    <#shadow-root>
      <h1 class=”title”></h1>
    </shadow-root>
  </div>
</body>

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

@pankajparkar

<body>
    <div>Hello, World!</div>
    <script>
      var host = document.querySelector(‘div’);
      var root = host.createShadowRoot();
      root.textContent = ‘Hello, Treehouse!’;
    </script>
</body>

3. HTML Imports

<head>
   <link 
    rel="import" 
    href="my-widget.html" />
</head>

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

@pankajparkar

4. Custom Element

<body>
  <my-navbar></my-navbar>
  <div class="content">
    <my-sidebar></my-sidebar>
    <my-main-content></my-main-content> 
  </div>
  <my-footer></my-footer>
</body>

@pankajparkar

Custom Element

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

Custom element should have dash used in their name, they can't be single word

@pankajparkar

Web Component Support

@pankajparkar

Custom Elements

class FancyDatePicker extends HTMLElement {}

window.customElements
  .define(‘fancy-datepicker’, FancyDatePicker);

@pankajparkar

It has below native DOM objects

  1. Attributes

  2. Events

  3. Properties

  4. Method

@pankajparkar

Custom Elements - Attributes

class FancyDatePicker extends HTMLElement {

  static observedAttributes = [‘current-date’];

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

Declarative

Imperative

@pankajparkar

Custom Elements - Properties

class FancyDatePicker extends HTMLElement {

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

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

@pankajparkar

Custom Elements - Event

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

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

@pankajparkar

Custom Elements - Method

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

@pankajparkar

Custom Elements - Reactions /Lifecycle Hooks

class FancyDatePicker extends HTMLElement {

  connectedCallback(){ … }

  disconnectedCallback(){ … }

  attributeChangedCallback(oldV, newV, key){ … }

  adoptedCallback(){ … }

}

@pankajparkar

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

@pankajparkar

Then why not use Web Components?

Text

https://developers.google.com/web/fundamentals/web-components/examples/howto-checkbox

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

@pankajparkar

Angular API looks similar to CE

NG

CE

@HostBindings

@Input

@Output

@Lifecycle Hooks

Attributes

Properties

CustomEvent

Reactions

@pankajparkar

@pankajparkar

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

web-component

Angular Component

@pankajparkar

Even other guys are doing it

SkateJS

@pankajparkar

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
}

@pankajparkar

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);

@pankajparkar

How it look in general

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

@pankajparkar

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>

@pankajparkar

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>

@pankajparkar

Demo Time

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

@pankajparkar

Future?

Angular Ivy Renderer (beta) +

Angular Elements

@pankajparkar

Don't try this on Prod

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

@pankajparkar

@pankajparkar

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

  • https://en.wikipedia.org/wiki/Unix_philosophy

Create cross framework Components using Angular Elements

By Pankaj Parkar

Create cross framework Components using Angular Elements

  • 924