Как проложить маршрут к модулю в качестве дочернего модуля-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
          }

https://github.com/angular/angular/issues/10958


Я нашел способ решить это. В принципе, я определяю свои маршруты так, как раньше, но на этот раз на верхнем дочернем уровне. Например, мой маршрут администратора:

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
  }
...