Angular Breadcrumb

别说谁变了你拦得住时间么 提交于 2021-01-29 07:54:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!