带有延迟加载模块的Angular Router Breadcrumbs

时间:2017-09-07 17:16:16

标签: angular angular-ui-router lazy-loading breadcrumbs

我正在使用Angular路由器动态添加面包屑。我已经按照几个例子让他们成功地工作了。

但是,如果我尝试合并一个延迟加载的模块,我会收到错误:

Root segment cannot have matrix parameters

我已经研究过该问题,但未能找到令人满意的信息/解决方案。

我已经创建了一个我想要完成的内容,以便从此页面上的大量代码中保存: https://plnkr.co/edit/505x2r

如何继续使用路由器创建的动态面包屑,但也使用延迟加载的路径。

import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';

import { RootComponent } from 'src/root/root.component';
import { IndexComponent } from 'src/index/index.component';
import { SignupComponent } from 'src/signup/signup.component';
import { SigninComponent } from 'src/signin/signin.component';

@NgModule({
    imports: [
        RouterModule.forChild([
            {
            path: '',
            component: RootComponent,
            children: [
                {
                    path: 'signin',
                    loadChildren: 'src/signin/signin.module#SigninModule'
                },
                {
                    path: 'signup',
                    component: SignupComponent,
                    data: {
                        breadcrumb: 'Sign Up'
                    }
                },
                {
                    path: '',
                    component: IndexComponent
                }
            ]
        }
    ])
],
exports: [
    RouterModule
]
})
export class RootRoutingModule {}

2 个答案:

答案 0 :(得分:4)

感谢Robert,Alex Beugnet和DAG的评论,让我们走上了正确的解决方案!

最后的插件在这里:https://plnkr.co/edit/iedQjH?p=preview

以下是我遇到的简明问题:

首先,我有懒惰的加载路线,我在路线上以面包屑的形式获得了数据。当运行getBreadcrumbs时,面包屑标签将显示两次。我通过添加以下几行解决了这个问题:

  if (
    child.snapshot.url.map(segment => segment.path).length === 0
  ) {
      return this.getBreadcrumbs(child, url, breadcrumbs);
  }

其次,我的路由只是一个参数输入,但我需要在痕迹路径上列出它。通过映射child.snapshot.url并将段指定给标签来解决此问题。

const routeArray = child.snapshot.url.map(segment => segment.path);
for ( let i = 0; i < routeArray.length; i++ ) {
    label = routeArray[i];
}

第三,我需要显示参数以及下一个路径的标签,无论是立即加载还是通过模块延迟加载。我还遇到了以下需要拆分的路径和适当分配的标签:

{
    path: ':id/products',
    loadChildren: 'src/products/products.module#ProductsModule',
    data: {
      breadcrumb: 'Products'
    }
}

                {
                  path: 'orders/:id',
                  component: OrderComponent,
                  data: {
                    breadcrumb: 'Orders'
                  }
                },

两者的解决方案是:

  for ( let i = 0; i < routeArray.length; i++ ) {
    if ( Object.keys(child.snapshot.params).length > 0 ) {
      if ( this.isParam(child.snapshot.params, routeArray[i]) ) {
        label = routeArray[i];
      } else {
        label = child.snapshot.data[ROUTE_DATA_BREADCRUMB];
      }
    } else {
      label = child.snapshot.data[ROUTE_DATA_BREADCRUMB];
    }
    const routeURL = routeArray[i];
    url += `/${routeURL}`;
    const breadcrumb: BreadCrumb = {
      label: label,
      params: child.snapshot.params,
      url: url
    };
    breadcrumbs.push(breadcrumb);
  }

private isParam(params: Params, segment: string) {
  for ( const key of Object.keys(params)) {
    const value = params[key];
    if ( value === segment ) {
      return true;
    }
  }
  return false;
}

有了所有好东西,有一个问题:你必须拥有每个参数的路线

例如,如果您有网址:#/ quotes / 123456 / products / 123456 / Generic / Tissue,则需要以下路线:

{
  path: ':id',
  component: ProductComponent,
  data: 'data'
},
{
  path: ':id/:make',
  component: ProductComponent,
  data: 'data'
},
{
  path: ':id/:make/:model',
  component: ProductComponent,
  data: 'data'
}

最终你会得到一个可点击的面包屑,如下所示:

主页/行情/ 123456 /产品/ 123456 / Generic / Tissue

我正在研究的项目只需要我有一个参数......永远。

最后,我能够处理立即加载的路由和延迟加载的路由,这是我的最终目标。我确信有些情况我没有考虑过,但我觉得它非常可靠。

无论如何,我鼓励人们把这里的东西拿走并运行它。用任何更新给我拍一张便条,这样我就能做到这一点! THX!

答案 1 :(得分:0)

我发现了与问题有关的几个要素,并让它“看似”工作:

  • 您的方法getBreadcrumbs()在单个导航中被称为 3 次,这是一个问题。只需在函数开头添加console.log('I pass !');即可查看。

  • 我认为主要问题是你使用了一个延迟加载模块的路径。对于breadcrumb组件,它将使用SignUpModule中的空路径。这是因为你的breadcrumb组件将使用当前激活的路径为空('')的路径,并且会因为你没有任何内容/而有效地中断路由。更改组件中的这个部分将使它第一次工作,因为到延迟加载的模块路径的路由将被注册,并且它将能够注册非空的routerLink。

<强> breadcrumb.component.ts

   let routeURL = child.snapshot.url.map(segment => segment.path).join('/');
   if(routeURL.length == 0) {
     routeURL = 'toto';
   }
   url += `/${routeURL}`;  
  • 因此,您应该找到一种方法为延迟加载的模块使用空路由,以便/signup路径适用于其模块中的注册组件。该路线将能够正确注册。