2 min read

Angular 2 Breadcrumb Component

Emily Taylor

Update: This blog post is now out of date. angular2-crumbs has moved to angular-crumbs, the demo is based on angular-cli and the library supports Angular >=2.0.0 <5.0.0

The idea: a breadcrumb component that is driven from the router config.

This post is an explanation of the breadcrumb component in angular2-crumbs. The demo uses angular2-seed and has the following routes to list and display details about github repositories:

export const rootRouterConfig: Routes = [  
    {path: '', redirectTo: 'home', pathMatch: 'full'},  
    {path: 'home', ...},  
    {path: 'about', ...},  
    {path: 'github', ...,  
        children: [  
            {path: '', ...},  
            {path: ':org', ... },  
                children: [  
                    {path: '', ...},  
                    {path: ':repo', ...}  
                ]  
        }]  
    }  
];  

The breadcrumb component works by expecting a breadcrumb property in the route data collection for any route you want to display as a breadcrumb.

export const rootRouterConfig: Routes = [  
    {path: '', redirectTo: 'home', pathMatch: 'full'},  
    {path: 'home', ..., data: { breadcrumb: 'Home'}},  
    {path: 'about', ..., data: { breadcrumb: 'About'}},  
    {path: 'github', ..., data: { breadcrumb: 'GitHub'},  
        children: [  
            {path: '', ...},  
            {path: ':org', ..., data: { breadcrumb: 'Repo List'},  
                children: [  
                    {path: '', ...},  
                    {path: ':repo', ..., data: { breadcrumb: 'Repo'}}  
                ]  
        }]  
    }  
];  

It is loosely based on a number of solutions I found on Stack Overflow for creating a route-based breadcrumb component in Angular 2.

Based on the above route table, the component displays a simple breadcrumb which you can modify to suit your own styling needs:

Breadcrumb Demo

The component is largely just two files - a breadcrumb.component and breadcrumb.service (source) that watches events on the router and adds any breadcrumb data that it finds to a breadcrumb collection.

this.router.events.subscribe((routeEvent: RoutesRecognized) => {
    if (!(routeEvent instanceof RoutesRecognized)) return;

    let route = routeEvent.state.root;
    let url = "";

    this.breadcrumbs = [];

    while (route.children.length) {
        route = route.firstChild;
        if (!route.routeConfig.path) continue;

        url += `/${this.createUrl(route)}`;
        if (!route.data["breadcrumb"]) continue;

        this.breadcrumbs.push(this.createBreadcrumb(route, url));
    }
    this.onBreadcrumbChange.emit(this.breadcrumbs);
});

This works well and serves most needs, but ideally I also wanted to be able to set the breadcrumb for a route as the result of an API call.

The breadcrumb.service also exposes a changeBreadcrumb method which allows you to update the breadcrumb from anywhere in a similar way to components such as ng2-breadcrumb. The key difference with this implementation is we need to provide the route that we would like to change the name for.

An example of this can befound in the ngOnInit() method in repo-detail.component. Here we set the breadcrumb title on the Repository Details page to the name of the current Repository.

this.github.getRepoForOrg(this.org, this.repo)
    .subscribe(repoDetails => {
        ...
        this.breadcrumbService.changeBreadcrumb(this.route.snapshot, repoDetails.name);

    });

And hey presto, we have a dynamic breadcrumb title. Now rather than "Repo" on each individual repository as defined in our route config, we get the individual repository name:

Breadcrumb Title Demo

So there you have it - a Angular 2 breadcrumb component that uses your route config, but also allows you to dynamically set a breadcrumb description as the result of an API call.

As bit of an added extra - the above screenshot also demos updating the the page title. The smarts behind this can be found in app.component - in the sample implementation we subscribe to the breadcrumbChange event and use angular's built in TitleService to update the page title created from the breadcrumbs:

breadcrumbService.onBreadcrumbChange.subscribe((crumbs) => {
    this.titleService.setTitle(this.createTitle(crumbs));
});