Угловая ленивая загрузка с неработающей розеткой

Я создал папку продуктов, которая содержит продукты-home.component(родительский) и products-list.component(дочерний) с указанным выходом.

я получил Error: Cannot match any routes. URL Segment: 'products' при переходе к products-list используя ленивую загрузку.

Это работает, когда он нетерпеливо загружен

app.module.ts

@NgModule({
  imports:      [ ...,ProductsModule ]
})

products.module.ts

@NgModule({
  imports: [
    RouterModule.forRoot([
      {
        path: "products",
        component: ProductsHomeComponent,
        children: [
          {
            path: "products-list",
            component: ProductsComponent,
            outlet: "content"
          }
        ]
      }
    ])
  ]
})

Это не работает при ленивой загрузке

app.module.ts

const LazyRoutes: Routes = [
  {
    path: 'products',
    loadChildren: './products/products.module#ProductsModule'
  }
];
@NgModule({
  imports:      [ RouterModule.forRoot(LazyRoutes) ]
})

products.module.ts

@NgModule({
  imports: [
    RouterModule.forChild([
      {
        path: "",
        component: ProductsHomeComponent,
        children: [
          {
            path: "products-list",
            component: ProductsComponent,
            outlet: "content"
          }
        ]
      }
    ])
  ]
})

Stackblitz

3 ответа

Решение

Это известная проблема в angular - 22346 и 10981

Когда модуль загружается с отложенной загрузкой, путь к родительскому компоненту должен быть пустым. Это проблема здесь, дочерний компонент с именованным выходом работает только тогда, когда у родителя есть путь (не пустой).

Я получил это, добавив поддельный путь.

{
    path: "home", <--Here
    component: ProductsHomeComponent,
    children: [
      {
        path: "products-list",
        component: ProductsComponent,
        outlet: "content"
      }
    ]
}

Поскольку конфигурация маршрута изменена, мы должны изменить routerLink как 'products/home'

<a [routerLink]="['/products/home', { outlets: { 'content': ['products-list'] } }]">Navigate to Products(Products List)</a>

Обновление 2021 ... Протестировано от V7 до V12

Чтобы использовать именованный выход лениво загруженного модуля, вы должны перейти на страницы модуля в компоненте, в котором определен маршрутизатор. Например:

Учти это:

lazyModule.component.ts

      <div>
  <a [routerLink]="[{outlets: {namedRouter: 'innerComponent'}}]">Open Link in Named Route</a><br>
  <router-outlet></router-outlet>
  <router-outlet name = 'namedRouter'></router-outlet>
</div>

Щелчок по тегу привязки БУДЕТ показывать маршрут с именем «innerComponent» в выходе «namedRouter».

ОДНАКО ... По той или иной причине изменение маршрута для 'namedRouter' из любого другого вложенного компонента (независимо от того, находится ли он в том же модуле) НЕ БУДЕТ РАБОТАТЬ . В терминах кода:

вложенныйComp.component.ts

      <div>
  <button [routerLink]="{outlets: {namedRouter: 'aValidRoute'}}">IT SHOULD WORK, BUT IT DOESN'T</button> <!--- This will fail to resolve the route if called within the conteXt of the lazy loaded module. --->
</div>

Если вы хотите динамически изменять маршрут из других компонентов, я бы предложил реализовать элемент Observable (например, в lazyModule.component.ts), который прослушивает брошенные ему маршруты и вызывает изменение маршрутизатора. См. пример ниже:

некоторыеService.ts

      private routeBS: BehaviorSubject = new BehaviorSubject(null);
routeObs = this.routeBS.asObservable();

changeNamedRouterRoute(route: string): void {
  this.routeBS.next(route);
}

lazyModule.component.ts

      <div>
   <router-outlet></router-outlet>
   <router-outlet name = 'namedRouter'></router-outlet>
 </div>

 export class LazyModuleComponent implements OnInit {
   
   constructor(
     private service: SomeServiceService,
     private router: Router,
     private route: ActivatedRoute
   ) {}

   ngOnInit() {
     this.service.routeObs.subscribe(res => {
       this.router.navigate([{outlets: {namedRouter: res}}], {relativeTo: this.route.parent}).then(acc => {
           // do something when the router gives you the nod
       }).catch(err => {
           console.log(err);
           // do something when the router event fails
       });
     });
   }
 }

В других компонентах, которые должны напрямую устанавливать маршруты к 'namedRouter', внедрите службу 'someService' через конструктор И затем вызовите функцию службы changeNamedRouterRoute(), указав желаемый маршрут в качестве единственного аргумента.

НАДЕЮСЬ, ЭТО ПОМОЖЕТ КОМУ-ТО, я застрял на этом почти 6 часов, и интернет не дал мне никаких серьезных перерывов. Проблемы GitHub были закрыты из-за бездействия без закрытия, но я уверен, что некоторые могут найти это весьма полезным.

Эта работа для меня,

Следующая конфигурация в «роутинге» ленивого модуля:

      const routes: Routes = [
    {
      path: '',
      component: LazyDownloadComponent,
      children: [
        {
          path: 'test',
          outlet: 'left',
          loadChildren: () =>
            import('./modules/another.module').then(
              (m) => m.Another
            ),
        },
      ],
    },

Родительский компонент:

      <router-outlet name="left"></router-outlet>

адрес в браузере:

      http://localhost:4200/parentComponent/(left:test)

БУДЬТЕ ОСТОРОЖНЫ С "/" МЕЖДУ ПУТЬЮ И "("

Я надеюсь, что это поможет кому-то, как @taffy сделал для меня

Другие вопросы по тегам