角面包屑 [英] Angular Breadcrumb
问题描述
我正在尝试在我的个人项目(Angular 7)中实现面包屑.但是我无法按预期实现它.我发现了很多实现方法,但没有一个对我有用.
我输入URL时的要求: http://localhost:4200/personal-projects/2/backlog 是
个人项目> 2>待办事项
但是我得到的输出为:
2>待办事项
有人可以帮助我实现逻辑以按预期方式获得输出吗?我的路由模型如下:
const路由:路由= [{小路: '',redirectTo:'dashboard',pathMatch:已满"},{小路: '',组件:HomeDashboardComponent,孩子们: [{路径:仪表板",组件:DashComponent,数据: {面包屑:仪表板"}},{路径:个人项目",组件:PresonalProjectsComponent,数据: {面包屑:个人项目"}}]},{路径:"personal-projects/:projectId",组件:ProjectDetailsComponent,数据: {面包屑:"},孩子们: [{小路: '',redirectTo:'backlog',pathMatch:已满"},{路径:"sprint",组件:SprintComponent,数据: {面包屑:冲刺"}},{路径:待办事项",组件:BacklogComponent,数据: {面包屑:积压"}}]}];
breadcrumb.component.ts文件为:
公共面包屑:IBreadCrumb [];构造函数(专用路由器:路由器,专用ActivatedRoute:ActivatedRoute,){this.breadcrumbs = this.buildBreadCrumb(this.activatedRoute.root);}ngOnInit(){this.router.events.pipe(filter((event)=> Navigation实例的事件实例),uniqueUntilChanged(),).subscribe(()=> {this.breadcrumbs = this.buildBreadCrumb(this.activatedRoute.root);});}/***根据激活的路径递归构建面包屑.* @参数路线* @参数网址* @参数面包屑*/buildBreadCrumb(route:ActivatedRoute,url:string ='',面包屑:IBreadCrumb [] = []):IBreadCrumb [] {//如果没有可用的routeConfig,我们就在根路径上让标签= route.routeConfig&&route.routeConfig.data?route.routeConfig.data.breadcrumb:'';let isClickable = route.routeConfig&&route.routeConfig.data&&route.routeConfig.data.isClickable;让path = route.routeConfig&&route.routeConfig.data?route.routeConfig.path:'';//如果路由是动态路由,例如':id',请将其删除const lastRoutePart = path.split('/').pop();const isDynamicRoute = lastRoutePart.startsWith(':');如果(isDynamicRoute&& !! route.snapshot){const paramName = lastRoutePart.split(':')[1];路径= path.replace(lastRoutePart,route.snapshot.params [paramName]);标签= route.snapshot.params [paramName];}//在routeConfig中,完整路径不可用,//所以我们每次都重建它const nextUrl =路径?`$ {url}/$ {path}`:URL;const面包屑:IBreadCrumb = {标签:标签,网址:nextUrl,};//仅添加带有非空标签的路由const newBreadcrumbs =面包屑.label?[...面包屑,面包屑]:[...面包屑];如果(route.firstChild){//如果我们还不在当前路径上,//将有更多的孩子来照顾,以建立我们的面包返回this.buildBreadCrumb(route.firstChild,nextUrl,newBreadcrumbs);}返回newBreadcrumbs;}}
在这里发布我可能为时已晚,但是为了他人的利益,这是我的面包屑实现!我已经推荐了angular-breadcrumb npm软件包,并且是我自己量身定制的! https://www.npmjs.com/package/angular-breadcrumb ..>
breadcrumb.component.ts
从'@ angular/core'导入{组件}从"../../models/breadcrumb.model"导入{面包屑}从"../../services/breadcrumb.service"导入{BreadcrumbService}@零件({选择器:面包屑",模板:< nav>< ol>< li * ngFor =让面包屑成为面包屑" class ="breadcrumb-item">< a [routerLink] ="[breadcrumb.url]"> {{Breadcrumb.displayName}}</a></li></ol></nav>`})出口类BreadcrumbComponent {面包屑:面包屑[]构造函数(私有BreadcrumbService:BreadcrumbService){this.breadcrumbService.breadcrumbChanged.subscribe((crumbs:Breadcrumb [])=> {this.onBreadcrumbChange(crumbs)})}私人onBreadcrumbChange(crumbs:Breadcrumb []){this.breadcrumbs =面包屑}}
breadcrumb.model.ts
从"@ angular/router"导入{Route}出口类面包屑{displayName:字符串网址:字符串路线:路线|无效的}
breadcrumb.service.ts
从'@ angular/core'导入{Injectable,EventEmitter}从'@ angular/router'导入{Router,ActivatedRouteSnapshot,Event,NavigationEnd}从'../models/breadcrumb.model'导入{面包屑}@Injectable()出口类BreadcrumbService {BreadcrumbChanged = new EventEmitter< Breadcrumb []>(false)私人面包屑:面包屑[] = []构造函数(专用路由器:路由器){this.router.events.subscribe((routeevent)=> {this.onRouteEvent(routeEvent)})}onRouteEvent(routeEvent:Event){如果(!(routeEnd实例的NavigationEnd)){返回}//获取父路由快照让路由= this.router.routerState.root.snapshot让url =''const newCrumbs = []而(route.firstChild!= null){路线= route.firstChild如果(route.routeConfig === null){继续}如果(!route.routeConfig.path){继续}url + =`/$ {this.createUrl(route)}`//检查直到路由包含其中定义的标题如果(!route.data ['breadcrumb']){继续}const newCrumb = this.createBreadcrumb(route,url)newCrumbs.push(newCrumb)}//用新的面包屑列表重新分配面包屑列表this.breadcrumbs = newCrumbsthis.breadcrumbChanged.emit(this.breadcrumbs)}createBreadcrumb(路线:ActivatedRouteSnapshot,网址:字符串):面包屑{返回 {displayName:route.data ['breadcrumb'],网址:url,路线:route.routeConfig}}createUrl(route:any){回程路线route.url.map(function(s){return s.toString())).join('/')}}
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;
}
}
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('/')
}
}
这篇关于角面包屑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!