Best way to handle nested routers with shared objects

Sure. Let’s take an example. The top route is 'product/:id', it got two child routes '' (details page), and 'comments' page.

We want to share a common object, but the object is related to a single product id. new ProductService(id). If you use normal DI injection in constructor, you have to do

@inject(Factory.of(ProductService))
export class Details {
  constructor(getProductService) {
    this.getProductService = getProductService;
  }
  activate(params) {
    this.id = params.id;
    this.productService = this.getProductService(this.id);
  }
}

The problem is that this.productService produced by Factory.of is not a singleton, hence it’s not “shared” among details and comments pages. I used to have a special implementation SingletonFactory to guarantee singleton for same arguments (same input id in this case), but it was bit unnecessarily complex.

If you share object through route settings, it’s for sure the singleton (you created manually).

export class Product {
  configureRouter(config, router, params) {
    this.router = router;
    // Note the special 3rd param "params", it's largely undocumented.
    this.id = params.id;
    this.productService = new ProductService(this.id);
    // Load product before doing anything.
    return this.productService.loadProduct()
    .then(product => {
      config.map([
       {
          route: '', name: 'details',
          title: 'Details',
          nav: true,
          moduleId: './details',
          settings: {productService: this.productService}
        },
        {
          route: 'comments', name: 'comments',
          title: 'Comments',
          nav: true,
          moduleId: './comments',
          settings: {productService: this.productService}
        }
      ]);
   });
  }
}

FYI the 3rd param on configureRouter The easy way to customize child router based on parent router param

4 Likes