Angular-elements

vs stencil-js

Bo Vandersteene

@reibo_bo

Why?

Angular Components can be tough to use outside of angular templates, and even more so outside of Angular applications

Rob Wormald, Angular Team

Angular-connect 2017

What are angular-elements?

 packages @angular/elements

exports createCustomElement()

bridge from Angular's component interface and Change Detection to the build-in DOM API

How it works

Angular on the inside, standards on the outside

Bridge with DOM

@Inputs = properties

@hostbinding = attributes

@outputs = events

Lifecycle hooks

Transform components to custom elements

Code examples

@Component({
  selector: 'qone-top-nav',
  templateUrl: './top-nav.component.html'
  styleUrls: ['./top-nav.component.scss']
})
export class TopNavComponent implements OnInit {

  @Input()
  title: string;
  _links: Array<string>;
  @Output()
  open = new EventEmitter<string>();

  constructor() {
  }

  ngOnInit() {
  }
  
  @Input()
  set links(links: string) {
    this._links = links.split(',');
  }
}
@NgModule({
  imports: [
    BrowserModule,
    CommonModule
  ],
  declarations: [TopNavComponent],
  entryComponents: [TopNavComponent],
})
export class TopNavModule {
  ngDoBootstrap() {
  }
}
import 'zone.js/dist/zone';
import { platformBrowser } from '@angular/platform-browser';
import { TopNavModuleNgFactory } from './top-nav/top-nav.module.ngfactory';
import { createCustomElement } from '@angular/elements';
import { TopNavComponent } from './top-nav/top-nav.component';


platformBrowser()
  .bootstrapModuleFactory(TopNavModuleNgFactory)
  .then(({ injector }) => {
    const topNamCopmonent = createCustomElement(TopNavComponent, {injector})
    customElements.define('qone-top-nav', topNavComponent);
  });
import 'zone.js/dist/zone';
import { platformBrowser } from '@angular/platform-browser';
import { TopNavModuleNgFactory } from './top-nav/top-nav.module.ngfactory';
import { createCustomElement } from '@angular/elements';
import { TopNavComponent } from './top-nav/top-nav.component';


platformBrowser()
  .bootstrapModuleFactory(TopNavModuleNgFactory)
  .then(({ injector }) => {
    const topNamCopmonent = createCustomElement(TopNavComponent, {injector})
    customElements.define('qone-top-nav', topNavComponent);
  });
@NgModule(...)
export class TopNavModule {
  constructor(private readonly injector: Injector) {

  }

  ngDoBootstrap() {
    customElements.define(
      'qone-top-nav',
      createCustomElement(TopNavComponent, { injector: this.injector })
    );
  }
}
import 'zone.js/dist/zone';

import { platformBrowser } from '@angular/platform-browser';
import { TopNavModuleNgFactory } from './top-nav/top-nav.module.ngfactory';


platformBrowser()
  .bootstrapModuleFactory(TopNavModuleNgFactory);

How to use it

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>PageElements</title>

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="src/favicon.ico">
</head>
<body>
<qone-top-nav title="Test Angular elements"></qone-top-nav>

<script src="elements/page-elements.bundle.js"></script>
<script>
  const topNav = document.querySelector('qone-top-nav');
  topNav.addEventListener('open', (data) => {
    console.log(`open`, data);
  });
  const links = ['first link', 'second link', 'another link'];
  topNav.setAttribute('links', links.join(','));
</script>
</body>
</html>

Against Stencil-js

Both

  • Webcomponents
  • Early Phase
  • Typescript support
  • Performance
    • use runtime on the browser
  • Simple
  • Does not exist at runtime
  • New framework

Stencil-js

  • No new framework
  • Transform existing components
  • Webcomponents + Angular native
  • Angular under the hood

Angular

  • From Angular 6
  • Performance
    • Build size
    • Ivy?

angular-elements

By Bo Vandersteene