$30 off During Our Annual Pro Sale. View Details »

Custom Elements with Angular

Custom Elements with Angular

Slides from my talk about Angular Elements at Java Lounge in Zurich
Demo can be found at https://github.com/gassmannT/WorldCupComponent

Thomas Gassmann

September 19, 2018
Tweet

More Decks by Thomas Gassmann

Other Decks in Programming

Transcript

  1. Agenda 19.09.2018 JavaLounge - Angular Elements 3 ▪ Intro Angular

    Elements ▪ Web Components ▪ Getting started with Angular Elements ▪ Outlook v7
  2. 19.09.2018 JavaLounge - Angular Elements 5 «Angular is ideal for

    building complete applications, and our tooling, documentation and infrastructure are primarily aimed at this case.» Rob Wormald, Angular Team
  3. Platform 19.09.2018 JavaLounge - Angular Elements 6 Dependency Injection Decorators

    Zones Compile Binding Render Material Mobile Universal CLI Language Service Augury ngUpdate Router Animation i18n
  4. 19.09.2018 JavaLounge - Angular Elements 7 «[…] but it’s quite

    challenging to use in scenarios that don’t fit that specific Singe Page Application model.» Rob Wormald, Angular Team
  5. Use case 19.09.2018 JavaLounge - Angular Elements 8 ▪ Enhancing

    existing HTML Pages ▪ Content Management Systems ▪ Use components in other environments or frameworks ▪ Microfrontends ▪ Reuse components across teams
  6. Web Components 19.09.2018 JavaLounge - Angular Elements 11 Web Components

    are a set of features added by the W3C ▪ HTML Template: Template of the HTML ▪ Shadow DOM: DOM and style encapsulation ▪ HTML Imports: Imports in HTML ▪ Custom Elements: Ability to add to the HTML vocabulary
  7. Custom Elements 19.09.2018 JavaLounge - Angular Elements 13 Custom elements

    share the same API surface as native DOM objects: ▪ Attributes ▪ Properties ▪ Methods ▪ Events
  8. Create and Define a Custom Element 19.09.2018 JavaLounge - Angular

    Elements 14 class myElement extends HTMLElement { … } customElements.define('my-element', myElement);
  9. Reactions 19.09.2018 JavaLounge - Angular Elements 15 class myElement extends

    HTMLElement { connectedCallback() { ... } disconnectedCallback() { ... } }
  10. Attributes 19.09.2018 JavaLounge - Angular Elements 16 class myElement extends

    HTMLElement { static get observedAttributes() { return ['country']; } attributeChangedCallback(name, oldValue, newValue) { if (name === 'country') { // do something with newValue } } }
  11. Properties 19.09.2018 JavaLounge - Angular Elements 18 class myElement extends

    HTMLElement { get country() { return this.getAttribute('country'); } set country(val) { this.setAttribute('country', val); } }
  12. Custom Events 19.09.2018 JavaLounge - Angular Elements 20 class myElement

    extends HTMLElement { emitCountryChange() { this.dispatchEvent( new CustomEvent('country-change', { detail: this.country })); } }
  13. Custom Elements in Angular 19.09.2018 JavaLounge - Angular Elements 22

    <app-matches-by-country [country]="sui" (countryChanged)="foobar($event)" > </app-matches-by-country> => Angular has been designed for this
  14. Enter Angular Elements 19.09.2018 JavaLounge - Angular Elements 23 Provides

    a bridge from angular concepts to web components. ▪ @HostBinding() => Attributes ▪ @Input() => Properties ▪ @Output() => CustomEvents ▪ Lifecycle Hooks => Reactions
  15. Platform 19.09.2018 JavaLounge - Angular Elements 26 Dependency Injection Decorators

    Zones Compile Binding Render Material Mobile Universal CLI Language Service Augury ngUpdate Router Animation i18n
  16. First Steps 19.09.2018 JavaLounge - Angular Elements 27 Update Angular

    CLI Update Angular CLI to > 6 ng new angularElements Create a new Angular CLI project ng add @angular/elements Add support for angular elements ng g c matchToday -v Native Generate new component
  17. Component 19.09.2018 JavaLounge - Angular Elements 28 @Component({ selector: 'app-matches-today',

    templateUrl: 'matches-today.component.html’, styleUrls: ['matches-today.component.css’], encapsulation: ViewEncapsulation.ShadowDom }) export class MatchesTodayComponent implements OnInit { public matches$: Observable<Match[]>; constructor(private matchService: MatchService) {} ngOnInit() { this.matches$ = this.matchService.getTodayMatches(); } }
  18. Module 19.09.2018 JavaLounge - Angular Elements 29 @NgModule({ imports: [BrowserModule,

    HttpClientModule], declarations: [AppComponent, MatchesTodayComponent], entryComponents: [MatchesTodayComponent], providers: [] }) export class AppModule { … }
  19. Module 19.09.2018 JavaLounge - Angular Elements 30 export class AppModule

    { constructor(private injector: Injector) {} ngDoBootstrap() { const el1 = createCustomElement( MatchesTodayComponent, { injector: this.injector }); customElements.define('app-matches-today', el1); } }
  20. Use with Javascript 19.09.2018 JavaLounge - Angular Elements 32 const

    matchesToday = document.createElement('app- matches-today'); document.body.appendChild(matchesToday); matchesToday.country = 'SUI'; matchesToday.setAttribute('country', 'GER');
  21. Use with Custom Element API 19.09.2018 JavaLounge - Angular Elements

    33 const MatchToday = document.get('app-matches-today’); const matchToday = new MatchToday(); // or const matchToday = new MatchToday(differencInjector);
  22. Angular Elements are the Host Element 19.09.2018 JavaLounge - Angular

    Elements 34 export class TestComponent implements OnInit { constructor(el: ElementRef) { el.nativeElement // <- Angular Element } @HostListener('click’) onHostClick($event) { ... } @HostBinding('attr.selected') isActive: boolean; }
  23. Dependency Injection 19.09.2018 JavaLounge - Angular Elements 35 Plattform Injector

    (Renderer) Module Injector (Services) Component Injector (ElementRef)
  24. Dependency Injection in Angular Elements 19.09.2018 JavaLounge - Angular Elements

    36 Plattform Injector (Renderer) Module Injector (Services) Element Injector (ElementRef) Element Injector (ElementRef)
  25. Module 19.09.2018 JavaLounge - Angular Elements 37 export class AppModule

    { constructor(private injector: Injector) {} ngDoBootstrap() { const el1 = createCustomElement( MatchesTodayComponent, { injector: this.injector }); customElements.define('app-matches-today', el1); } }
  26. Content Projection 19.09.2018 JavaLounge - Angular Elements 40 <app-test> <span>Hallo

    JavaLounge</span> </app-test> @Component({ selector: 'app-test’, template: ` <ng-content></ng-content> ` }) export class TestComponent { }
  27. Shadow DOM 19.09.2018 JavaLounge - Angular Elements 41 @Component({ …

    encapsulation: ViewEncapsulation.ShadowDom }) export class MatchesTodayComponent implements OnInit { … }
  28. Angular Elements in V6 19.09.2018 JavaLounge - Angular Elements 43

    ▪ It is just the beginning ▪ Size is too big for shipping in non Angular projects ▪ Will be much better with Ivy (V7) ▪ Will be much easier with V7 ▪ Browser Support.
  29. Outlook V7 19.09.2018 JavaLounge - Angular Elements 44 @Component({ selector:

    'app-test', template: '...', customElement: true }) export class TestComponent { ... }
  30. Combine bundle in a single file 19.09.2018 JavaLounge - Angular

    Elements 46 npm install concat --save-dev Install package concat npm install fs-extra --save-dev Install package fs-extra "build:elements": "ng build --prod --output- hashing none && node build-elements.js" Add script command
  31. build-elements.js 19.09.2018 JavaLounge - Angular Elements 47 const fs =

    require('fs-extra'); const concat = require('concat'); (async function build() { const files = [ './dist/WorldCupComponent/runtime.js', './dist/WorldCupComponent/polyfills.js', './dist/WorldCupComponent/main.js' ]; await fs.ensureDir('elements’); await concat(files, 'elements/world-cup.js'); console.info('Wold Cup Element created successfully!'); })();
  32. 19.09.2018 JavaLounge - Angular Elements 49 It is just the

    beginning. Stay tuned with Angular 7
  33. Ressources 19.09.2018 JavaLounge - Angular Elements 50 ▪ github.com/gassmannT/WorldCupComponent ▪

    thomasgassmann.net ▪ swissangular.com ▪ m.trivadis.com/angular ▪ angular-academy.ch