Hello Angular 6 Elements

Yet another blog post on Angular 6 elements.

Quick Start

A starter “hello world” project can be found in GitHub. To build the element, checkout the project and run the following command:

>npm run build:elements

This should generate the file hello-world.js in the elements folder. To use the newly created Angular element, embed the javascript file in a html file:

<!DOCTYPE html>
<body>
 <hello-world></hello-world>
 <scr\ipt type="text/javascript" src="hello-world.js"></script>
</body>
</html>

NgModule

The hello-world element is implemented as a Angular component the same way as in an Angular app. To use it as a custom element outside of Angular, it is bootstrapped a bit differently in the app module file (app.module.ts)

...
import { createCustomElement } from '@angular/elements';
import { HelloWorldComponent } from './hello-world/hello-world.component';
@NgModule({  
     declarations: [HelloWorldComponent],
     imports: [BrowserModule],
     entryComponents: [HelloWorldComponent],
     providers: []})
export class AppModule {
 constructor(private injector: Injector) {
 }
 ngDoBootstrap() { 
     const el = createCustomElement(HelloWorldComponent, {
          injector: this.injector }); 
     customElements.define('hello-world', el); 
 }
}

Note the missing bootstrap attribute in the @NgModule definition for an Angular app. Instead the component is registered with the browser as a custom element in the ngDoBootstrap() method using the createCustomElement() API exported by @angular/elements package.

The building and export of custom elements in Angular 6 is still a work in progress. A custom script and build task (build:elements) from this blog post is used here to concatenate the output javascript files into the single hello-world.js file.

Advertisements

RouteReuseStrategy for Route Caching in Angular

This post explains how to implement RouteReuseStrategy to support custom control of route snapshot caching in Angular. Typical use case is a list page which a user can search for a list of items and then select and navigates to a particular item’s detail pages. When the user clicks the back button in the browser, the Angular app should return to the list page displaying the same items as before, using the previous search criteria.

Other advantages of caching route for rendering is faster page load and reduce network traffic.

To achieve the above in Angular, we need to implement the RouteReuseStrategy to tell Angular not to destroy a component but to save it for re-rendering. There are few blog posts online already with example implementations. This blog will focus more on describing the mechanics of the interface and its methods

RouteReuseStretagy

Below is a skeleton implementation of a custom RouteReuseStrategy:

import { Injectable } from '@angular/core';
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';

@Injectable()
export class AppRouteReuseStrategyService implements RouteReuseStrategy {

     handles: {[key: string]: DetachedRouteHandle} = {};

     constructor() { }

     shouldDetach(route: ActivatedRouteSnapshot): boolean {
           // To Be Implemented
     }

     store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
           // To Be Implemented
     }

     shouldAttach(route: ActivatedRouteSnapshot): boolean {
           // To Be Implemented
     }

      retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
          // To Be Implemented
      }

      shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
          // To Be Implemented
      }
}

shouldReuseRoute()

This is the first method to consider. If returns true, none of the other methods will be called. For example, when we are already reusing the current route snapshot. Note the future argument refers to the route that you come from previously. For example if the app navigates from item list page to item details page, curr would refer to the route for the item detail page and future to the route for the item list page.

shouldDetach() and store()

If the method shouldRouteReuse returns false, the method shouldDetach will be called to determine whether the current route snapshot should be detached and stored. If it returns true, the store method will be called. A handle to the detached route snapshot (of type DetachedRouteHandle) is provided as argument to the method so it can store it for later use.

Note if a null handle is provided to the method, it should erase the stored value for the input route. See the API documentation here.

Note once a route snapshot is detached, it is the developer’s responsibility to manage its lifecycle and perform any clean up as needed for proper memory management.

shouldAttach() and retrieve()

Similar to above,

If the method shouldReuseRoute returns false, the method shouldAttach will be called to determine if a cached route should be used. If it returns true, the method retrieve will be called to retrieve the saved handle to the detached route previously stored.

Note the shouldAttach method is also a good place to clean up any stored snapshots. For example when a user has logged out or the snapshot has got staled, in which case we should not be rendering the store snapshot. The method should then return false and the stored handle to route snapshot should be removed from storage.

That’s it. Hope above gives some clarity on what the class RouteReuseStrategy does.