问题
I am trying to implement breadcrumb in my personal project(Angular 7). But I am unable to implement it as expected. I have found lot of implementation but none of them worked for me.
My requirement when i enter the URL : http://localhost:4200/personal-projects/2/backlog is
Personal Project > 2 > Backlog
But i am getting output as:
2 > Backlog
Can anyone help me to implement logic to get the output as expected? My routing model is as follows:
const routes: Routes = [
{
path: '',
redirectTo: 'dashboard',
pathMatch: 'full'
},
{
path: '',
component: HomeDashboardComponent,
children: [
{
path: 'dashboard',
component: DashComponent,
data: {
breadcrumb: 'Dashboard'
}
},
{
path: 'personal-projects',
component: PresonalProjectsComponent,
data: {
breadcrumb: 'Personal Project'
}
}
]
},
{
path: 'personal-projects/:projectId',
component: ProjectDetailsComponent,
data: {
breadcrumb: ''
},
children: [
{
path: '',
redirectTo: 'backlog',
pathMatch: 'full'
},
{
path: 'sprint',
component: SprintComponent,
data: {
breadcrumb: 'Sprint'
}
},
{
path: 'backlog',
component: BacklogComponent,
data: {
breadcrumb: 'backlog'
}
}
]
}
];
breadcrumb.component.ts file as:
public breadcrumbs: IBreadCrumb[];
constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
) {
this.breadcrumbs = this.buildBreadCrumb(this.activatedRoute.root);
}
ngOnInit() {
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
distinctUntilChanged(),
).subscribe(() => {
this.breadcrumbs = this.buildBreadCrumb(this.activatedRoute.root);
});
}
/**
* Recursively build breadcrumb according to activated route.
* @param route
* @param url
* @param breadcrumbs
*/
buildBreadCrumb(route: ActivatedRoute, url: string = '', breadcrumbs: IBreadCrumb[] = []): IBreadCrumb[] {
// If no routeConfig is avalailable we are on the root path
let label = route.routeConfig && route.routeConfig.data ? route.routeConfig.data.breadcrumb : '';
let isClickable = route.routeConfig && route.routeConfig.data && route.routeConfig.data.isClickable;
let path = route.routeConfig && route.routeConfig.data ? route.routeConfig.path : '';
// If the route is dynamic route such as ':id', remove it
const lastRoutePart = path.split('/').pop();
const isDynamicRoute = lastRoutePart.startsWith(':');
if (isDynamicRoute && !!route.snapshot) {
const paramName = lastRoutePart.split(':')[1];
path = path.replace(lastRoutePart, route.snapshot.params[paramName]);
label = route.snapshot.params[paramName];
}
// In the routeConfig the complete path is not available,
// so we rebuild it each time
const nextUrl = path ? `${url}/${path}` : url;
const breadcrumb: IBreadCrumb = {
label: label,
url: nextUrl,
};
// Only adding route with non-empty label
const newBreadcrumbs = breadcrumb.label ? [...breadcrumbs, breadcrumb] : [...breadcrumbs];
if (route.firstChild) {
// If we are not on our current path yet,
// there will be more children to look after, to build our breadcumb
return this.buildBreadCrumb(route.firstChild, nextUrl, newBreadcrumbs);
}
return newBreadcrumbs;
}
}
回答1:
May be I am too late to post here, but for the benefit of others, here's my breadcrumb implementation! I have referred angular-breadcrumb npm package and tailored on my own! https://www.npmjs.com/package/angular-breadcrumb.
breadcrumb.component.ts
import { Component } from '@angular/core'
import { Breadcrumb } from '../../models/breadcrumb.model'
import { BreadcrumbService } from '../../services/breadcrumb.service'
@Component({
selector: 'breadcrumb',
template: `
<nav>
<ol>
<li *ngFor="let breadcrumb of breadcrumbs" class="breadcrumb-item">
<a [routerLink]="[breadcrumb.url]">{{ breadcrumb.displayName }}</a>
</li>
</ol>
</nav>
`
})
export class BreadcrumbComponent {
breadcrumbs: Breadcrumb[]
constructor(private breadcrumbService: BreadcrumbService) {
this.breadcrumbService.breadcrumbChanged.subscribe((crumbs: Breadcrumb[]) => {
this.onBreadcrumbChange(crumbs)
})
}
private onBreadcrumbChange(crumbs: Breadcrumb[]) {
this.breadcrumbs = crumbs
}
}
breadcrumb.model.ts
import { Route } from '@angular/router'
export class Breadcrumb {
displayName: string
url: string
route: Route | null
}
breadcrumb.service.ts
import { Injectable, EventEmitter } from '@angular/core'
import { Router, ActivatedRouteSnapshot, Event, NavigationEnd } from '@angular/router'
import { Breadcrumb } from '../models/breadcrumb.model'
@Injectable()
export class BreadcrumbService {
breadcrumbChanged = new EventEmitter<Breadcrumb[]>(false)
private breadcrumbs: Breadcrumb[] = []
constructor(private router: Router) {
this.router.events.subscribe((routeEvent) => { this.onRouteEvent(routeEvent) })
}
onRouteEvent(routeEvent: Event) {
if (!(routeEvent instanceof NavigationEnd)) { return }
// Get the parent route snapshot
let route = this.router.routerState.root.snapshot
let url = ''
const newCrumbs = []
while (route.firstChild != null) {
route = route.firstChild
if (route.routeConfig === null) { continue }
if (!route.routeConfig.path) { continue }
url += `/${this.createUrl(route)}`
// check until the routes contains title defined in it
if (!route.data['breadcrumb']) { continue }
const newCrumb = this.createBreadcrumb(route, url)
newCrumbs.push(newCrumb)
}
// reassign breadcrumb list with new breadcrumb list
this.breadcrumbs = newCrumbs
this.breadcrumbChanged.emit(this.breadcrumbs)
}
createBreadcrumb(route: ActivatedRouteSnapshot, url: string): Breadcrumb {
return {
displayName: route.data['breadcrumb'],
url: url,
route: route.routeConfig
}
}
createUrl(route: any) {
return route && route.url.map(function (s) { return s.toString() }).join('/')
}
}
来源:https://stackoverflow.com/questions/57985653/angular-breadcrumb