Search code examples
angularroutesangular-components

How can I supply different data based on the route?


I am working on a large Angular-based project with many (let's say, > 200) lazy-loaded modules. Each module has the same UI, so each module can be represented by the same component. (The difference between modules is that they offer different dynamically instantiated sub-components. Thus, what I really want to achieve is having the same UI in each module, but supplying a different set of available sub-components depending on the route - you can imagine that as e.g. Type<MySubComponent> instances that are going to be fed to component outlets.)

Each module has an individual route, that is, the route determines which module we are in.

How do I define this in Angular?

  • As far as I've understood, routes in Angular always point to a component (which is to be displayed when navigating to said route). Not to some underlying service or other class that provides data, but to the UI itself.
  • Thus, a straightforward OOP way would be to define my one module-UI-component as a base class, then derive a module-specific component in each module that "fills in some blanks" (i.e. implements some abstract methods that supply the data).
    The problem here is: Apparently, the @Component decorator is not inherited even if my subclass does not specify one itself. As a result, I'd have to duplicate the exact same @Component decorator with the same template and style URLs for each of the 200+ modules, which I consider a severe violation of the DRY principle and thus bad design. Without doing so, I'm getting error NG6001, as can be reproduced by this code:
@Component({
    template: '<div></div>'
})
abstract class BaseComponent {
    abstract get moduleSpecificStuff(): string;
}

export class ConcreteComponent extends BaseComponent {
    get moduleSpecificStuff(): string {
        return 'This is the concrete module!';
    }
}

Thus, how can I route to the same UI everywhere without having lots of duplicate code and getting some different data/contents supplied under each route?


As a further caveat, there must not be any global list of all routes. I've got a list of special modules, each of which will know the routes to its sub-modules and lazy-load them as required. That is, for each of those routes, the same component must be registered, but different data must be supplied.


Solution

  • It seems that the Route.data attribute is the right place to store this kind of data. This is where arbitrary route-specific data can be supplied.

    The component (even if it is the same component for many routes) can then inject ActivatedRoute and retrieve the data either as an observable from data or once, e.g. upon initialization, via the snapshot property.