Create Reusable Custom Elements
with Angular Elements

David Stanich

https://dstanich.github.io/angular-elements-presentation/

Background

  • Advisory Software Engineer
  • IBM Watson Health
  • Frontend development
  • Co-organizer Rochester FED@IBM meetup
Twitter: @dstanich GitHub: dstanich

What are custom elements?

Custom Elements

  • Custom HTML tags that encapsulate functionality
  • Registered by a JavaScript API
  • Lifecycle methods
  • Can extend existing tag

              customElements.define('my-element', MyElement);
            

              
            
MDN Docs

Browser Support (Details)

Web Components

Web Components are several standards combined which allow reusable custom elements that are completely encapsulated.

Custom Elements / Web Components

Custom Elements are part of Web Component standard
  • Custom elements
  • Shadow DOM
  • HTML templates
MDN Docs

Embedded Example



Angular Elements
@angular/elements

What?

  • First released with Angular v6
  • Packages Angular components as custom elements
  • Registers components with CustomElementRegistry
  • Contains Angular runtime to bridge with DOM
Elements Documentation

Why?

  • Angular within React/Vue/Vanilla
  • Pieces of app may be Angular (ex: CMS)
  • Migration path for AngularJS
  • Inject Angular within JSP/Jade/etc
  • Easier dynamic components within Angular

Embedded Example

Setting Up

Summary

  1. Install dependencies
  2. Update config if no polyfill
  3. Configure module
  4. Define elements
  5. Setup build

Install Dependencies

NPM install or ng add

                // No polyfill; limited browser support
                npm install @angular/elements --save-dev

                // Polyfill included
                ng add @angular/elements
            

Update Config If No Polyfill

If no polyfill, force output to es2015

                {
                  // ...
                  "compilerOptions": {
                    // ...
                    "target": "es2015"
                  }
                }
            

Configure Module

  • Remove bootstrap property
  • Add empty ngDoBootstrap() method
  • Add entryComponents property
  • Import createCustomElement from elements

Define Elements


                constructor(private injector: Injector) {
                  const el = createCustomElement(TitleComponent, 
                      { injector: this.injector }
                  );
                  customElements.define('custom-title', el);

                  // ...
                }
            

Setup Build

angular-cli does not have build for elements

                // Prod build, disable hashing in output
                ng build --prod --output-hashing none

                // Concat the scripts into single .js file
                cat runtime* polyfills* main* scripts* > elements.js
            

Example

Using the Custom Elements

Overview

  • Import .js file into HTML
  • Use custom element like normal tag
  • Inputs are attributes
  • Outputs are custom events

HTML Import


                <!DOCTYPE html>
                <html lang="en">
                  <head>
                    <!-- ... -->
                    <script src="./elements.js"></script>
                  </head>
                  <body>
                    <!-- ... -->
                    <my-custom-element></my-custom-element>
                    <!-- ... -->
                  </body>
                </html>
            

HTML / JS


                
                
                
            

                // Outputs as custom events
                element = document.getElementById('id');
                if (element) {
                  element.addEventListener('outputName', (item: any) =>
                    // some logic
                  );
                }
            

Within Vue


              
              
            

Within React


              // REACT: App.tsx
              class App extends Component {
                render() {
                  return (
                    
); } }

Examples

Considerations

Custom Element Considerations

  • Element name restrictions
  • String attributes only
  • Browser support (polyfills?)

@angular/elements Considerations

As of March-2019
  • Built result isn't that small (our demo ~ 240KB)
  • angular-cli doesn't yet have build path for it
  • Building each element indepenently will repeat framework code

Frameworks & Custom Elements

  • Frameworks may have issues w/custom elements
  • Custom Elements Everywhere websites
    • Set of custom element tests
  • Angular: 100%
  • Vue: 100%
  • React: 71%

Exporting from React/Vue

React and Vue have similar features to @angular/elements to export components as custom elements. Both official and unofficial packages.

Vue

React

Future

  • Better browser support for custom element
  • Smaller bundles (Ivy)
  • angular-cli support (hopefully)
  • Potential for more generic web!

Questions / Discussion