Angular 11 не может выполнить маршрутизацию к именованному выходу

#angular #routes

#angular #маршруты

Вопрос:

У нас есть базовое приложение с 2 вкладками, каждая из которых имеет свой именованный выход

 <mat-tab-group>
    <mat-tab label="Tab1">
        <router-outlet name="tab1"></router-outlet>
    </mat-tab>
    <mat-tab label="Tab2">
        <router-outlet name="tab2"></router-outlet>
    </mat-tab>
</mat-tab-group>
 

Один из 2 именованных выходов просто отображает компонент, и это нормально. Для второго мы хотим иметь возможность маршрутизировать между разными представлениями, поэтому мы создали его собственный модуль и отложили его загрузку.

Маршрутизация приложений выглядит следующим образом

 const routes: Routes = [{
    path: '',
    children: [{
        path: '',
        redirectTo: '/home',
        pathMatch: 'full'

    }, {
        path: 'login',
        loadChildren: () => import('./login/login.module').then(m => m.LoginModule)
    },
    {
        path: 'home',
        loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
    }]
}]
 

Маршрутизация домашней страницы выглядит следующим образом

 const routes: Routes = [{
    path: '',
    component: HomeComponent,
    children: [{
        path: '',
        component: Tab1Component,
        outlet: 'tab1'
    }, {
        path: '',
        outlet: 'tab2',
        loadChildren: () => import('./tab2/tab2.module').then(m => m.Tab2Module)
    }]
}];
 

Tab2Module реализован следующим образом

 const routes: Routes = [{
    path: '',
    component: Tab2Child1Component
}, {
    path: 'tab2-child',
    outlet: 'tab2',
    component: Tab2Child2Component
}]
 

Tab2Child1Component отображается нормально, но мы не можем перейти к Tab2Child2Component.

Я пытаюсь выполнить следующее:

 this.router.navigate([{ outlets: { tab2: 'tab2-child' } }], { relativeTo: this.route });
 

Я вижу при отслеживании, что маршрутизатор действительно пытается выполнить маршрутизацию /home/(tab2:tab2-child) , но в итоге он просто перенаправляет обратно /home с ошибкой:

  Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'home'
Error: Cannot match any routes. URL Segment: 'home'
 

Stackblitz демонстрирует ошибку:
https://stackblitz.com/edit/angular-ivy-pv5jsi

Комментарии:

1. Эй, я не уверен, что правильно понимаю, вы хотите, чтобы он перенаправлялся на : https://angular-ivy-w8jqek.stackblitz.io/home;tab2=tab2-child ?

Ответ №1:

У вас есть две проблемы с вашим дизайном, из-за которых он не работает.

  1. Ваш домашний компонент имеет пустой путь, который не работает с именованными выходами. Они работают, только если указан путь к компоненту. Возможно, это изменится в будущем, поскольку в Angular GitHub есть открытая ошибка, касающаяся этого.
  2. Компоненты, отображаемые в именованных выходах, должны быть прямыми дочерними элементами компонента, который содержит выходы в конфигурации маршрутизации. Ваша конфигурация с loadChildren for tab2 похожа на компонент внутри tab2, который будет иметь больше внутренних маршрутов, что в вашем случае неверно, поскольку у вас нет другого выхода маршрутизатора в Tab2Child1Component .

Чтобы изменить ваш образец на что-то, что работает, вам нужно добавить путь к HomeComponent внутренней HomeModule части . Для отложенной загрузки вкладок вам нужно поместить все вкладки в один модуль, который загружается как дочерние элементы домашнего компонента.

Вот моя реализация HomeModule с необходимыми изменениями.

 const routes: Routes = [
  {
    path: '',
    redirectTo: 'hc',
    pathMatch: 'full'
  },
  {
    path: 'hc',
    component: HomeComponent,
    loadChildren: () => import("./tab.module").then(m => m.TabModule)
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  declarations: [HomeComponent]
})
export class HomeModule {}
 

И реализация модуля tab, который определяет вкладки для обоих выходов.

 const routes: Routes = [
  {
    path: '',
    component: Tab1Component,
    outlet: "tab1"
  },
  {
    path: '',
    outlet: 'tab2',
    component: Tab2Child1Component
  },
  {
    path: 'tab2-child',
    outlet: 'tab2',
    component: Tab2Child2Component
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  declarations: [Tab2Child1Component, Tab2Child2Component]
})
export class TabModule {}
 

В модуле приложения перенаправление непосредственно на вспомогательный путь по какой-то причине перенаправление в модуле не работает, если вы перенаправляете только на home.

  {
   path: "",
   redirectTo: "/home/hc",
   pathMatch: "full"
 },
 

Вот ссылка на форк вашего StackBlitz с полной реализацией.

Если для вас требуется иметь отдельные модули отложенной загрузки для каждой вкладки, вам необходимо создать отдельные компоненты для каждой вкладки, внутри которых есть один выход маршрутизатора, чтобы отобразить дочерние компоненты вкладки, чтобы вы получили двухуровневую структуру навигации. Поскольку я не знаю, каков ваш точный вариант использования, я не могу сказать, будет ли это лучшим решением.

Комментарии:

1. Я считаю, что (1) было исправлено в Angular 11, т. Е. Теперь у вас могут быть пустые пути для именованных выходов. Ваша разветвленная версия, похоже, не работает для меня, т.Е. Я все еще получаю ту же ошибку маршрутизации. В конце концов я переместил все маршруты в единый список под домашним компонентом. Я не возражаю, если они загружены лениво или нет, это не большие накладные расходы. Я просто хотел, чтобы конфигурации маршрутизации с 2 вкладками были разделены.

2. Я исправил свой образец. Очевидно, что первая проблема не исправлена в Angular 11, потому что я забыл добавить имя для маршрута, и это не сработало. Теперь с добавленным именем это работает.

3. Я отмечаю этот ответ как правильный, поскольку он практически такой же, с которым я в итоге столкнулся самостоятельно.