user4676340
user4676340

Reputation:

Dynamically build breadcrumbs from router

I am trying to build a breadcrumbs path for my application, with the less amount of code possible.

For that, I am listening to router events, and getting the data from the current route snapshot (assuming every route has a crumb data).

Right now, I have a working solution, building the route automatically.

But it doesn't work as soon as the user navigates : I don't know how to detect the direction of the routing (down the tree, or up), so I don't know how to add/remove the items from the crumbs.

I thought about going through the whole tree again (in case the user doesn't navigate from a parent to a child - or vice versa -), but I don't know how to do that either.

I have created a simple stackblitz to show my issue :

https://stackblitz.com/edit/angular-ysbzkp?file=src%2Fapp%2Fapp.component.ts

The related code of the tree reading :

constructor(
  private router: Router,
  private route: ActivatedRoute,
) {
  this.router.events.pipe(
    filter(event => event instanceof ActivationStart),
    map((event: ActivationStart) => event.snapshot.data),
    map(data => data && data.crumb || undefined),
    filter(v => !!v),
  ).subscribe(crumb => this.crumbs.push(crumb));
}

Upvotes: 0

Views: 493

Answers (1)

user4676340
user4676340

Reputation:

Seems like I figured out the answer myself.

Instead of ActivationStart, the router should listen to ActivationEnd, but also NavigationEnd.

On activation end, the router sends events in reverse order, containing all the routes.

By putting them in a buffer, it becomes possible to reverse the buffer on navigation end, then clear it, resulting in a trail of crumbs that is coherent with the application.

Here is the stackblitz and the related code :

https://stackblitz.com/edit/angular-rjg2ja?file=src/app/app.component.ts

let buffer = [];

this.router.events.pipe(
  filter(event => event instanceof ActivationEnd),
  map((event: ActivationEnd) => event.snapshot.data),
  map(data => data && data.crumb || undefined),
  filter(v => !!v),
).subscribe(crumb => buffer.push(crumb));

this.router.events.pipe(
  filter(event => event instanceof NavigationEnd)
).subscribe(event => {
  this.crumbs = buffer.reverse();
  buffer = [];
});

Upvotes: 1

Related Questions