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

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
          }

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

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

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