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

F8980be26d3f8c298c19e3e30ac0dbe1?s=128

Thomas Gassmann

September 19, 2018
Tweet

Transcript

  1. Custom Elements with Angular JavaLounge 19.09.2018 Thomas Gassmann @gassmannT

  2. Thomas Gassmann Senior Consultant, Trainer, Speaker thomasgassmann.net @gassmannT 19.09.2018 JavaLounge

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

    Elements ▪ Web Components ▪ Getting started with Angular Elements ▪ Outlook v7
  4. Angular Elements 19.09.2018 JavaLounge - Angular Elements 4

  5. 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
  6. 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
  7. 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
  8. 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
  9. 19.09.2018 JavaLounge - Angular Elements 9

  10. 19.09.2018 JavaLounge - Angular Elements 10 Web Components

  11. 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
  12. 19.09.2018 JavaLounge - Angular Elements 12 <app-matches-today></app-matches-today>

  13. Custom Elements 19.09.2018 JavaLounge - Angular Elements 13 Custom elements

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

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

    HTMLElement { connectedCallback() { ... } disconnectedCallback() { ... } }
  16. 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 } } }
  17. 19.09.2018 JavaLounge - Angular Elements 17 <app-matches-by-country country="sui"></app-matches-by-country>

  18. 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); } }
  19. 19.09.2018 JavaLounge - Angular Elements 19 let matches = document.querySelector('app-matches-by-country’);

    matches.country = 'ger';
  20. Custom Events 19.09.2018 JavaLounge - Angular Elements 20 class myElement

    extends HTMLElement { emitCountryChange() { this.dispatchEvent( new CustomEvent('country-change', { detail: this.country })); } }
  21. 19.09.2018 JavaLounge - Angular Elements 21 let matches = document.querySelector('app-matches-by-country’);

    matches.addEventListener('country-change', event => { ... });
  22. 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
  23. 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
  24. A lot of framework exists 19.09.2018 JavaLounge - Angular Elements

    24
  25. Getting started 19.09.2018 JavaLounge - Angular Elements 25

  26. 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
  27. 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
  28. 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(); } }
  29. Module 19.09.2018 JavaLounge - Angular Elements 29 @NgModule({ imports: [BrowserModule,

    HttpClientModule], declarations: [AppComponent, MatchesTodayComponent], entryComponents: [MatchesTodayComponent], providers: [] }) export class AppModule { … }
  30. 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); } }
  31. 19.09.2018 JavaLounge - Angular Elements 31 <app-matches-today></app-matches-today>

  32. 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');
  33. 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);
  34. 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; }
  35. Dependency Injection 19.09.2018 JavaLounge - Angular Elements 35 Plattform Injector

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

    36 Plattform Injector (Renderer) Module Injector (Services) Element Injector (ElementRef) Element Injector (ElementRef)
  37. 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); } }
  38. 19.09.2018 JavaLounge - Angular Elements 38 Dependency Injection works!

  39. Demo 19.09.2018 JavaLounge - Angular Elements 39

  40. 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 { }
  41. Shadow DOM 19.09.2018 JavaLounge - Angular Elements 41 @Component({ …

    encapsulation: ViewEncapsulation.ShadowDom }) export class MatchesTodayComponent implements OnInit { … }
  42. Demo 19.09.2018 JavaLounge - Angular Elements 42

  43. 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.
  44. Outlook V7 19.09.2018 JavaLounge - Angular Elements 44 @Component({ selector:

    'app-test', template: '...', customElement: true }) export class TestComponent { ... }
  45. 19.09.2018 JavaLounge - Angular Elements 45 How to use it

    today in non Angular Projects?
  46. 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
  47. 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!'); })();
  48. Demo 19.09.2018 JavaLounge - Angular Elements 48

  49. 19.09.2018 JavaLounge - Angular Elements 49 It is just the

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

    thomasgassmann.net ▪ swissangular.com ▪ m.trivadis.com/angular ▪ angular-academy.ch
  51. Thank you Thomas Gassmann @gassmannT thomasgassmann.net thomas.gassmann@trivadis.com 19.09.2018 JavaLounge -

    Angular Elements 51
  52. None