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

@AngularConnect, November 2017
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?

Angular 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
A look into the future: Angular Elements
By Andrei Antal
A look into the future: Angular Elements
ng-europe 2018 Lightning Talk - A look into the future: Angular Elements by Andrei Antal
- 3,285