Как проложить маршрут к модулю в качестве дочернего модуля-Angular 2 RC 5
Я в процессе обновления приложения, над которым я работаю, до последнего кандидата на выпуск Angular 2. В рамках этой работы я пытаюсь использовать спецификацию NgModule и переносить все части моего приложения в модули. По большей части, это уже очень хорошо за исключением проблемы с маршрутизацией.
"@angular/common": "2.0.0-rc.5",
"@angular/compiler": "2.0.0-rc.5",
"@angular/core": "2.0.0-rc.5",
"@angular/forms": "0.3.0",
"@angular/http": "2.0.0-rc.5",
"@angular/platform-browser": "2.0.0-rc.5",
"@angular/platform-browser-dynamic": "2.0.0-rc.5",
"@angular/router": "3.0.0-rc.1",
мое приложение построено как композиция модулей, при этом несколько модулей склеиваются вместе как дети родительского модуля. Например, у меня есть Модуль администратора, состоящий из модуля уведомлений, модуля пользователей и модуля Telphony (например). Маршруты к этим модулям должны выглядеть так...
/admin/notifications/my-notifications
/admin/users/new-user
/admin/telephony/whatever
в более ранней версии маршрутизатора, это было легко сделать, используя "детей"
export const AdminRoutes: RouterConfig = [
{
path: "Admin",
component: AdminComponent,
Children: [
...UserRoutes,
...TelephonyRoutes,
...NotificationRoutes
]
}
]
в другом файле, как часть субмодулей, я бы также определил отдельные маршруты модулей, т. е.
export const UserRoutes: RouterConfig = [
{
path: "users",
component: userComponent,
children: [
{path: "new-user", component: newUserComponent}
]
}
]
все это сработало очень хорошо. В процессе обновления до модулей я переехал все в свои собственные отдельные файлы маршрутизации вместо этого, так что теперь эти два выглядят больше как это
const AdminRoutes: Routes = [
{path: "admin", component: AdminComponent}
]
export const adminRouting = RouterModule.forChild(AdminRoutes)
и
const UserRoutes: Routes = [
path: "users",
component: userComponent,
children: [
{path: "new-user", component: newUserComponent}
]
]
export const userRouting = RouterModule.forChild(UserRoutes)
со всем этим на месте у меня есть UsersModule, который импортирует userRouting, а затем AdminModule, который импортирует adminRoutes и UsersModule. Моя мысль была, что с UsersModule является дочерним AdminModule, маршрутизация будет работать как раньше. К сожалению, это не так, я в конечном итоге с маршрутом пользователей, который просто
/users/new-user
вместо
/admin/users/new-user
кроме того, из-за этого компонент new-user не загружается в розетку маршрутизатора компонента my admin, который сбрасывает стиль и навигацию моего приложения.
Я не могу для жизни меня придумать, как ссылаться на маршруты моего UserModule как дети моего AdminModule. Я попытался сделать это по-старому и получить ошибки о маршрутах, находящихся в двух модулях. Очевидно, так как это недавно выпущенная документация по некоторым из этих случаев немного ограничена.
любая помощь, которую любой может предоставить, будет очень признательна!
7 ответов
хорошо, после возиться с этим в течение большей части выходных я получил его работает на моем конце. В конце концов мне удалось сделать следующее:--20-->
- экспортировать все
Routes
для каждого модуля, который вы хотите направить. Не импортируйте ни одного изRouterModule.forChild()
в дочерние модули. - экспорт компонент, видимый из определений маршрута Чайлдса в определении модуля Чайлдса.
- импорт (что означает Typescript
import
ключевое слово) все маршруты как обычно и используйте...
оператор для включения их под правильным путем. Я не мог заставить его работать с дочерним модулем, определяющим путь, но иметь его на родителе отлично работает (и совместим с ленивой загрузкой).
в моем случае у меня было три уровня в иерархии такой:
- Root (
/
)- редактор (
editor/:projectId
)- запрос (
query/:queryId
) - страница (
page/:pageId
)
- запрос (
- переднего (
about
)
- редактор (
следующие определения работают для меня для /editor/:projectId/query/:queryId
путь:
// app.routes.ts
import {editorRoutes} from './editor/editor.routes'
// Relevant excerpt how to load those routes, notice that the "editor/:projectId"
// part is defined on the parent
{
path: '',
children: [
{
path: 'editor/:projectId',
children: [...editorRoutes]
//loadChildren: '/app/editor/editor.module'
},
]
}
маршруты редактора выглядят так:
// app/editor/editor.routes.ts
import {queryEditorRoutes} from './query/query-editor.routes'
import {pageEditorRoutes} from './page/page-editor.routes'
{
path: "", // Path is defined in parent
component : EditorComponent,
children : [
{
path: 'query',
children: [...queryEditorRoutes]
//loadChildren: '/app/editor/query/query-editor.module'
},
{
path: 'page',
children: [...pageEditorRoutes]
//loadChildren: '/app/editor/page/page-editor.module'
}
]
}
и заключительная часть для QueryEditor выглядит так:
// app/editor/query/query-editor.routes.ts
{
path: "",
component : QueryEditorHostComponent,
children : [
{ path: 'create', component : QueryCreateComponent },
{ path: ':queryId', component : QueryEditorComponent }
]
}
однако, чтобы сделать эту работу, генерал Editor
необходимо импортировать и экспорт QueryEditor
и QueryEditor
нужно экспортировать QueryCreateComponent
и QueryEditorComponent
поскольку они видны при импорте. Неспособность сделать это приведет к ошибкам по строкам Component XYZ is defined in multiple modules
.
обратите внимание, что ленивая загрузка также отлично работает с этой настройкой, в этом случае дочерние маршруты не должны импортироваться, конечно.
У меня была та же проблема.
ответ здесь довольно хорош, используя loadChildren:
{
path: 'mypath',
loadChildren : () => myModule
}
Я нашел способ решить это. В принципе, я определяю свои маршруты так, как раньше, но на этот раз на верхнем дочернем уровне. Например, мой маршрут администратора:
const AdminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
children: [
...setupRoutes
]
}
]
export const adminRouting = RouterModule.forChild(AdminRoutes)
мой файл маршрутов установки импортируется из подзоны, которая определяет собственные маршруты, включая больше детей. Уловка заключается в том, что этот файл экспортирует объект "Routes", а не RouterModule.результат forChild.
после того, как это настроено, я удалил дочерние и дочерние маршруты из определения подмодулей. Затем мне пришлось экспортировать все компоненты, используемые в маршрутах, из каждого из подмодулей, как Маркус упоминал выше. Как только я это сделал, маршруты начали работать так, как я хотел.
Я не думаю, что мне действительно нравится это решение, так как мой родительский модуль слишком много знает о маршрутах дочернего модуля. Но, по крайней мере, это простой способ обойти его для RC5, и он не протекает все мои компоненты повсюду. Я пойду вперед и отмечу Маркуса. ответ как ответ, так как он поставил меня на правильный путь.
Я думаю, что 2.0.0 rc5 сейчас не интересует. Но is работает в Angular 4, может быть, тоже рано.
@NgModule({
imports: [
RouterModule.forRoot([
{path: "", redirectTo: "test-sample", pathMatch: "full"},
{
path: "test-sample",
loadChildren: () => TestSampleModule
}
])
],
exports: [RouterModule],
declarations: []
})
export class AppRoutingModule{}
@NgModule({
imports: [
RouterModule.forChild([{
path: "",
component: TestSampleComponent,
children: [
{path: "", redirectTo: "home", pathMatch: "full"},
{
path: "home",
loadChildren: () => HomeModule
},
{
path: "about",
loadChildren: () => AboutModule
}
]
}
])
],
exports: [RouterModule],
declarations: []
})
export class TestSampleRoutingModule {}
@NgModule({
imports: [RouterModule.forChild([{
path: "",
component: AboutComponent
}
])],
exports: [RouterModule]
})
export class AboutRoutingModule {}
учитывать на loadChildren: () => {...}
. Это не ленивая загрузка.
Посмотреть подробнее feat: поддержка иерархии NgModules без ленивой загрузки
когда вы используете ngModules и RC5, конфигурация маршрутизации вашего родительского модуля не должна ничего знать о маршрутизации дочерних модулей. Вам нужно только определить маршруты для вашего родительского модуля здесь. Кроме того, вы должны импортировать дочерний модуль в родительский модуль. В дочернем модуле вы должны определить свои маршруты следующим образом:
export const childRoutes: Routes = [
{
path: 'someChild',
component: SomeChildComponent,
children: [
{ path: '', component: SomeChildSubComponent1 },
{ path: 'comp1', component: SomeChildSubComponent1 },
{ path: 'comp2', component: SomeChildSubComponent2 }
]
}
];
Это позволит вам иметь url-адрес, как /someParent / someChild / comp1 - и компоненты отображаются в их соответствующий маршрутизатор-розетка. Обратите внимание: вы должны declace компонент на пустой путь. Иначе вы не сможете ориентироваться на вас, дети.
у меня это тоже работает, и если вам действительно не нужно отображать все родительские компоненты в иерархии, я думаю, что мое решение намного элегантнее.
ключ к пониманию моего подхода заключается в том, что все маршруты, независимо от того, как глубоко вложенные в модули добавляются к основному модулю. Быстрый пример, скажем, у нас есть DepartmentModule
и EmployeeModule
который мы хотели бы перейти к использованию этого URL
/department/1/employee/2
в этот момент мы увидим детали сотрудника 2. Конфигурирование маршруты для department
на department.routing.ts
и employee
на employee.routing.ts
будет не работайте так, как мы намеревались, и вы заметите, что вы можете перейти к
/employee/2
из корневого компонента, в то время как
/department/1/employee/2
рухнет (путь не найден). Типичная конфигурация маршрута в этом сценарии будет выглядеть следующим образом:
export const departmentRoutes: Routes = [
{ path: 'department', component: DepartmentComponent, children: [
{ path: '', component: DepartmentsComponent },
{ path: ':id', component: DepartmentDetailsComponent }
]}
];
export const employeeRoutes: Routes = [
{ path: 'employee', component: EmployeeComponent, children: [
{ path: '', component: EmployeesComponent },
{ path: ':id', component: EmployeeDetailsComponent }
]}
];
и EmployeeModule
будет импортирован DepartmentModule
. Как я уже сказал, это, к сожалению, не работает.
однако, с всего одно изменение:
export const employeeRoutes: Routes = [
{ path: 'department/:id/employee', component: EmployeeComponent, children: [
{ path: '', component: EmployeesComponent },
{ path: ':id', component: EmployeeDetailsComponent }
]}
];
подвох в том, что DepartmentModule
больше не принимает активного участия, как только вы переходите к employee
URL, но вы все еще можете получить доступ к каждому параметру ActivatedRoute
:
export class EmployeeDetailsComponent {
departmentId: number;
employeeId: number;
constructor(route: ActivatedRoute) {
route.parent.params.subscribe(params =>
this.departmentId= +params['id'])
route.params.subscribe(params =>
this.employeeId= +params['id']);
}
}
интересно, должен ли это быть официальный подход, но пока это работает для меня до следующего изменения от команды Angular 2 .
использовать loadChildren
. Все нормально. Но при перезапуске процесса сборки вы получите ошибку сборки. Вы должны сопоставить экспортированный символ с loadChildren
.
import { ChildModule } from './child/child.module';
export function childRouteFactory() {
return ChildModule;
}
...
{
path: 'child',
loadChildren: childRouteFactory
}
...