在 Angular 中设置面包屑时遇到的问题 [英] Facing problems setting up breadcrumbs in angular

查看:34
本文介绍了在 Angular 中设置面包屑时遇到的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从早上开始就试图解决面包屑相关的问题,但仍然无法解决.我正在使用 Angular 10 并尝试使用 angular 路由来让面包屑在我的应用程序的每个页面的顶部工作.这是我的问题和代码:

I am trying to solve a breadcrumbs related problem since morning but still cannot get hold on it. I am using Angular 10 and trying to make use of angular routing to get breadcrumbs working on the top of every page for my application. Here is my problem and the code:

问题:我在应用程序中启用了延迟加载,目前面包屑似乎只能部分工作,因为我导航到的每个组件只显示一个面包屑.

The problem: I have enabled lazy-loading in the application and currently the breadcrumbs seems to be working only partially as only one breadcrumb is getting shown for every component where I navigate to.

例如当我按照下面的代码从图书馆导航到书籍组件时,我应该看到 'Library ->Book Foo''Library ->Book Bar' 分别作为面包屑.

e.g. When I navigate from Library to books component as per code below, I should see 'Library -> Book Foo' and 'Library -> Book Bar' respectively as breadcrumbs.

但是当我导航到任何此类相关组件时,我只能看到像 'Book Foo''Book Bar' 这样的单个链接.

But I am only seeing single links like 'Book Foo' and 'Book Bar' when I navigate to any of such relevant component.

目录结构

app
  app.component.ts
  app.component.html
  app.component.scss
  app-routing.module.ts
    |
    |
    |
library
  LibraryComponent.component.ts
  LibraryComponent.component.html
  library-routing.module.ts
    |
    |
    |    
books
  BookFoo
    BookFooComponent.component.ts
    BookFooComponent.component.html
    BookFooComponent.component.scss
  BookBar
    BookBarComponent.component.ts
    BookBarComponent.component.html
    BookBarComponent.component.scss
  books.module.ts

books.module.ts

const routes: Routes = [

  { path: 'book-foo', 
    component: BookFooComponent,
    data: {
      breadcrumb:'Book Foo'
    }
  },

  { path: 'book-bar', 
    component: BookBarComponent,
    data: {
      breadcrumb:'Book Bar'
    }
  },

];

@NgModule({
  declarations: [
    BookFooComponent,
    BookBarComponent
  ],
  imports: [
    CommonModule,
    _SharedModule,
    RouterModule.forChild(routes)
  ],
  exports: [
    RouterModule
  ]
})
export class BooksModule { }

library-routing.module.ts

const routes: Routes = [
  { path: '', component: NestedroutingComponent,
    children:[
      { path: 'library', 
        component: LibraryComponent,
        data: {
          breadcrumb: 'Library'
        }, 
      },
      { path: 'books', loadChildren: () => import('../books/books.module').then(m => m.BooksModule) }
    ] 
  }
];

bread-crumb.service.ts(我从位于 here)

@Injectable()
export class BreadcrumbService {
  
  breadcrumbChanged = new EventEmitter<IBreadCrumb[]>(false)

  private breadcrumbs: IBreadCrumb[] = []

  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): IBreadCrumb {
    return {
      displayName: route.data['breadcrumb'],
      url: url,
      route: route.routeConfig
    }
  }

  createUrl(route: any) {
    return route && route.url.map(function (s) { return s.toString() }).join('/')
  }
}

breadcrumbComponent.component.ts(该组件根据上面列出的服务获取面包屑)

breadcrumbComponent.component.ts (this component fetches breadcrumbs based on service listed above)

@Component({
  selector: 'app-shared-breadcrumbs',
  templateUrl: './shared-breadcrumbs.component.html',
  styleUrls: ['./shared-breadcrumbs.component.scss']
})

export class SharedBreadcrumbsComponent implements OnInit {

  ngOnInit(): void {
    
  }

  breadcrumbs: IBreadCrumb[];

  constructor(private breadcrumbService: BreadcrumbService) {
    this.breadcrumbService.breadcrumbChanged.subscribe((crumbs: IBreadCrumb[]) => {
      this.onBreadcrumbChange(crumbs)
    })
  }

  private onBreadcrumbChange(crumbs: IBreadCrumb[]) {
    this.breadcrumbs = crumbs
  }
}

breadcrumbComponent.component.html(在所有页面上显示面包屑的模板)

breadcrumbComponent.component.html (template to show breadcrumbs on all pages)

<nav>
  <ol style="padding: 0%; display: flex;">              
    <li *ngFor="let breadcrumb of breadcrumbs" class="breadcrumb-item">
      <a [routerLink]="[breadcrumb.url]">{{ breadcrumb.displayName }}</a>
    </li>
  </ol>
</nav>

我尝试了什么?

我觉得我已经用尽了我所有的选择,首先我试图改变我的延迟加载结构来修改它以包含一些子组件,但一切都变得一团糟.我尝试阅读更多有关延迟加载的详细信息,但我发现有关动态面包屑的信息很少.

I feel like I have exhausted all my options, first I tried to change my lazy-loading structure to modify it to contain some child components, but everything is getting messed up. I tried reading about lazy-loading much more into detail but I found very less information on dynamic breadcrumbs.

起初我尝试过这个教程但是遇到了同样的问题,并且在单击时也会导航到所有错误的路径.在这一点上,我很确定我将不得不更改一些路线,以便遵循父子关系,但不知道从哪里开始.

At first I had tried this tutorial but faced same problems, and it also navigates to all wrong paths upon clicking. At this point I am pretty sure that I will have to change some of my routes so that parent, child relationship is followed, but don't know where to start.

如果有人可以帮助我,我会很高兴.谢谢.

Would be really glad if someone can help me out. Thanks.

推荐答案

另一种获得面包屑的方法 - 是的,我知道这是不可扩展的 - 是数据"是一个数组(我说另一个"是因为这个答案与您发布的代码无关)

Another aproach to get a breadcrumb -yes, I know that is not scalable- is that the "data" was an array (I say "another" because this answer has nothing about the code you post)

{ path: 'book-foo', 
    component: BookFooComponent,
    data: {
      breadcrumb:[{link:'../',text:'Library'},{text:'Book Foo'}]
    }
  },

那么,只需要

    <nav aria-label="breadcrumb">
      <ol >
        <li *ngFor="let bread of breadcrumbs|async;let last=last" [ngClass]="{'active':last}">
          <ng-container *ngIf="!last">
             <a routerLink="{{bread.link}}">{{bread.text}}</a>
             <span class="arrow right"></span>
          </ng-container>
          <span *ngIf="last">{{bread.text}}</span>
        </li>
      </ol>
    </nav>

export class BreadCrumsComponent{
    breadcrumbs = this.activatedRoute.data.pipe(map(res => res.breadcrumbs))
    constructor(private activatedRoute: ActivatedRoute) { }

}

好吧,我使用了一个带有链接、文本的对象数组,也可以只使用文本.

Well, I use an array of object with link,text, is possible make it only with text.

这篇关于在 Angular 中设置面包屑时遇到的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆