A look into the future

       Angular Elements

Andrei Antal

ngBucharest

ng-europe

2 february 2018

Bonjour!

Andrei Antal

@andrei_antal

  • frontend engineer (since i can remember)
  • web & JS technologies enthusiast
  • perpetual learner

Bucharest, Romania

organizer for ngBucharest

@ngBucharest

groups/angularjs.bucharest

WARNING!

DON'T TRY THIS AT HOME

Angular Labs

@AngularMIX, October 2017

http://youtu.be/ljsOPm4MMEo

@AngularConnect, November 2017

http://youtu.be/ljsOPm4MMEo

There's no excuse for not using Angular on your next project...

...but it might get challenging to use if your app is not a SPA

Rob Wormald, Angular Team (paraphrase)

Angular Components can be tough to use outside Angular

Rob Wormald, Angular Team

Why components outside of Angular?

Web Components Standard

HTML Templates
Shadow DOM

HTML Imports
Custom Elements

<body>
....
<my-datepicker date="02/02/2018"></my-datepicker>
...
</body>

Exposes:

  • attributes/properties
  • bindable events

Encapsulates

  • template (structure)
  • styles
  • logic
const myPicker = document.querySelector('my-dateicker');

elem.addEventListener('date-change', ev => { /* change */});

Web Components work with Angular out of the box

<angular-app>
  ...
  <my-datepicker
    [attr.locale]="someLocale"
    [date]="someDate"
    (dateChange)="changeDate()"
  >
  </my-datepicker>
  ...
</angular-app>

Why not web components everywhere?

Why not Polymer?

<iron-ajax
    auto
    url="https://www.googleapis.com/youtube/v3/search"
    params='{"part":"snippet", "q":"polymer", "key": "YOUTUBE_API_KEY", "type": "video"}'
    handle-as="json"
    on-response="handleResponse"
    debounce-duration="300"></iron-ajax>

Angular Components can be tough to use outside Angular   

Angular Elements

- Angular Components packaged

as Web Components -

How does it work?

  • Hosting Angular Components inside Custom Elements (NgElement) - "Angular on the inside, standards on the outside"

  • Bridge between Angular Components and DOM

    • @Inputs - properties

    • @HostBinding - attributes

    • @Outputs - events

    • Lifecycle hooks

  • Generate a bundle.js file than you need to include in your app

  • Use it in any application - Angular, static HTML, React, Vue, etc.

  • Self-bootstrapping - drop the element on the page and it works

@Component()
NgElement
@HostBinding
@Input()
@Output()
Lifecycle Hooks
Attributes
Properties
Events
Reactions

"compile"

register as Custom Element

How does it work?

Bridging Angular and DOM APIs

Write your average Angular Component

@Component({
  selector: 'ng-component',
  template: `<h1>
      Hello World, my name is {{myName}} !
  </h1>
  <button (click)="onClick()">Hi !</button>`,
  styles: [...],
  encapsulation: ViewEncapsulation.Native,
})
export class NgComponent implements OnInit {
  @Input() myName;
  @Output() sayHi = new EventEmitter<string>();

  ngOnInit() {
    this.myName = 'Andrei'
  }

  onClick() {
    this.sayHi.emit(`Yo, wassup ${this.myName}?.`);
  }
}

Create the Components Module

import { MyNgComponent } from './ng-component';


@NgModule({
  imports: [BrowserModule],
  declarations: [MyNgComponent],
  entryComponents: [MyNgComponent]
})
export class CustomElementsModule {
  ngDoBootstrap() {}
}

Register the custom elements

import { platformBrowserDynamic } from '@angular/platform...';
import { registerAsCustomElements } from '@angular/elements';

import { CustomElementsModule } from './app';
import { MyNgComponent } from './ng-component';

registerAsCustomElements([MyNgComponent], () => {
  return platformBrowserDynamic()
    .bootstrapModule(CustomElementsModule);
})

Consume the custom element

<head>
  ...
  <script src="my-ngComponent.bundle.js">
  </script>
  ...
</head>
<body>
  ...
  <ng-component></ng-component>
  ...
</body>
<head>
  ...
  <script src="mini-angular.js"></script>
  <script src="my-ngComponent.js"></script>
  ...
</head>
<body>
  ...
  <my-ngComponent></my-ngComponent>
  ...
</body>

Looks familiar?

<head>
  ...
  <script src="jquery.min.js"></script>
  <script src="jquery.my-datepicker.js">
  </script>
  ...
</head>
<body>
  <div class="datepicker"></div>
  <script>
    $('.datepicker').myDatepicker({...})
  </script>
</body>

DEMO TIME!

fingers crossed!

The magical, reusable web component compiler

import { Component, Prop } from '@stencil/core';

@Component({
  tag: 'my-first-component',
  styleUrl: 'my-first-component.scss'
})
export class MyComponent {

  @Prop() name: string;

  @Event() someEvent: EventEmitter;

  someEventHandler(data) {
    this.someEvent.emit(data);
  }

  render() {
    return (
      <p>
        My name is {this.name}
      </p>
    );
  }
}

SkateJS

Effortless custom elements for modern view libraries.


import 'skatejs-web-components';
import { Component, h, prop } from 'skatejs';
import styles from './styles';

class SKTags extends Component {
  static props = {
    delimiter: prop.string({attribute: true, default: ' '})
  }

  renderCallback() {
    return <div>
      <style>{styles}</style>
      <div class="wrapper">
        <span class="tags"></span>
        <input type="text" autofocus="true" class="input"/>
      </div>
    </div>
  }
}

customElements.define('sk-tags', SKTags);

What's next?

What's next?

What's next?

An​gular dynamic pages talk - AngularConnect 2017

Ward Bell and Jesus Rodriguez

Angular docs - angular.io

The future?

WARNING!

DON'T TRY THIS AT HOME

Merci Beaucoup!

@andrei_antal

Reach me at:

antal.a.andrei@gmail.com

#community4thewin

Made with Slides.com