Как проложить маршрут к модулю в качестве дочернего модуля-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 не загружается в розетку маршрутизатора моего компонента admin, который сбрасывает стиль и навигацию моего приложения.
Я не могу для жизни меня придумать, как ссылаться на маршруты моего UserModule как дети моего AdminModule. Я попытался сделать это по-старому и получить ошибки о маршрутах, находящихся в двух модулях. Очевидно, так как это недавно выпущенная документация вокруг некоторых из этих случаев немного ограничена.
любая помощь, которую кто-либо может предоставить, будет очень признательна!
7 ответов:
хорошо, после возиться с этим в течение большей части выходных я получил его работает на моем конце. То, что сработало для меня в конце концов было сделать следующее:
- экспортировать все
Routes
для каждого модуля, который вы хотите направить. Не импортируйте ни один изRouterModule.forChild()
в дочерние модули.- экспорт компонент, который виден из определений маршрута childs в определении модуля childs.
- импорт (имеется в виду машинопись
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)
мой установочный файл маршрутов импортируется из вложенной области, которая определяет собственные маршруты, включая больше детей. Загвоздка в том, что этот файл экспортирует объект "маршруты", а не RouterModule.для ребенка результат.
после того, как это настроено, я удалил дочерние и дочерние маршруты из определения подмодулей. Затем мне пришлось экспортировать все компоненты, используемые в маршрутах, из каждого из подмодулей, как и Маркус, упомянутый выше. Как только я это сделал, маршруты начали работать так, как я хотел.
Я не думаю, что мне действительно нравится это решение, так как мой родительский модуль слишком много знает о маршрутах дочернего модуля. Но, по крайней мере, это простой способ обойти его для RC5, и он не пропускает все мои компоненты повсюду. Я пойду вперед и Марк Маркус' ответ как ответ, так как он поставил меня на правильный путь.
Я думаю, что 2.0.0 rc5 сейчас не интересует. Но это работает в угловой 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-и компоненты отображаются в их соответствующий маршрутизатор-розетка. Обратите внимание: вы должны деклассировать компонент для пустого пути. Иначе вы не сможете ориентироваться на своих детей.
я получил это, чтобы работать, а также и если вы на самом деле не нужно, чтобы сделать все родительские компоненты в иерархии я думаю, что мое решение гораздо более элегантным.
ключ к пониманию моего подхода заключается в том, что все маршруты, независимо от того, как глубоко вложенные в модули добавляются к основному модулю. Небольшой пример, Допустим у нас есть
DepartmentModule
иEmployeeModule
который мы хотели бы перейти к использованию этого URL/department/1/employee/2
в этот момент мы увидим детали сотрудника 2. Конфигурирование маршруты для
department
наdepartment.routing.ts
иemployee
inemployee.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 } ...