We saw in previous post that we can have dynamic routes thanks to generic/reusable components. The question is how to make them configurable to customize them enough to not look too generic and make the UI not understable enough by end users.

The solution can be summarized in two points:

  1. Configure the route activating a component adding the required component metadata,
  2. Make the component read the route metadata to auto-configure itself.

Configure a route

Angular added to its route API (ActivatedRoute or its snapshot flavor) a data attribute to host the route metadata:

{
  path: 'home',
  component: HomeComponent,
  data: { title: 'Home' }
}

In this simple example, the home route has a title configured in its data and HomeComponent can read it to render it without knowing it upfront.

Read the route configuration from your component

Reading data can be done in two ways:

  1. Subscribing to data changes - if you plan to update it with another part of your application,
  2. Reading current version (snapshot) directly as a snapshot route attribute.

Here are what both cases can look like for our home component:

constructor(route: ActivatedRoute) {
  this.title = route.snapshot.data.title;
}

 

constructor(route: ActivatedRoute) {
  route.data.subscribe(d => {
    this.title = d.title;
  });
}

 

Then you can use title class attribute in your view/template or to compute other properties depending your component logic.

Conclusion

Using this solution enables to have generic and very reusable components. If you use widely this pattern, I recommend you to start typing the data you request in your route. Used at wider scale, you can also pass a provider function in data enabling to request data from the component without having to assume on the shape of the data object. This is very useful when composing component and reading the data from multiple level of components (components used in the main or sub components dynamically). The function would act as a registry (the component request a key and gets the associated data instead of having to build a big object in the route).

Combined with previous post, it enables to have a CRUD UI very adapted to each entity without any crazy code. The components are just renderers and all the logic is mainly in converting the backend model to the route bindings/data. It is also quite easy to debug and you can even optimize previous post by storing previous flavor of the router in local storage very easily to bootstrap faster (without waiting for the initializer actually).

So, overall, it is very interesting to start making render oriented components - application logic agnostic. It can look like being too much technical but it actually makes the application simpler and easier to test and update in time.

From the same author:

In the same category: