How to get directions to a module as a child module - Angular 2 RC 5

In the process of updating the application, I work with the latest candidate for the release of Angular 2. As part of this work, I try to use the NgModule specification and transfer all parts of my application to modules. For the most part, this went very well, with the exception of the routing problem.

"@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", 

My application is built as a composition of modules, while several modules are glued together as children of the parent module. For example, I have an administrator module, which consists of a notification module, a user module, and a telephone module (for example). The routes to these modules should look like ...

 /admin/notifications/my-notifications /admin/users/new-user /admin/telephony/whatever 

In an earlier version of the router, this was easy to do with "children"

 export const AdminRoutes: RouterConfig = [ { path: "Admin", component: AdminComponent, Children: [ ...UserRoutes, ...TelephonyRoutes, ...NotificationRoutes ] } ] 

In another file, as part of the submodules, I would define the routes of the individual modules, as well as ie

 export const UserRoutes: RouterConfig = [ { path: "users", component: userComponent, children: [ {path: "new-user", component: newUserComponent} ] } ] 

All this worked very well. In the process of upgrading to modules, I moved everything to my own routing files, and now these two are more like this.

 const AdminRoutes: Routes = [ {path: "admin", component: AdminComponent} ] export const adminRouting = RouterModule.forChild(AdminRoutes) 

and

 const UserRoutes: Routes = [ path: "users", component: userComponent, children: [ {path: "new-user", component: newUserComponent} ] ] export const userRouting = RouterModule.forChild(UserRoutes) 

With all this in place, I have a UserModule that imports userRouting, and then an AdminModule that imports adminRoutes and UserModule. I thought that since UserModule is a child of AdminModule, routing will work the way it is used to. Unfortunately, this is not so, I end up with a user route that is simply

 /users/new-user 

instead

 /admin/users/new-user 

In addition, because of this, the new user component does not load into the router socket of my admin component, which cancels the style and navigation of my application.

I canโ€™t figure out for my whole life how to refer to the routes of my UserModule as children of my AdminModule. I tried to do it the old way and get errors about routes found in two modules. Obviously, as it is recently released, the documentation for some of these cases is slightly limited.

Any help anyone can provide would be greatly appreciated!

+50
angular angular2-routing
Aug 10 '16 at 17:03
source share
7 answers

Well, after I did this for most of the weekend, it ended with me. In the end, the following was done for me:

  • Export all Routes for each module that you want to route. Do not import any of the RouterModule.forChild() into child modules.
  • Export each component that is visible from the childs route definitions in the childs module definition.
  • Import (which means Typescript import ) all child routes, as usual, and use the ... operator to include them under the correct path. I could not get it to work with the child module that defines the path, but its presence on the parent computer works fine (and is compatible with lazy loading).

In my case, I had three levels in such a hierarchy:

  • Root ( / )
    • Editor ( editor/:projectId )
      • Query ( query/:queryId )
      • Page ( page/:pageId )
    • Front ( about )

The following definitions work for me for the path /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' }, ] } 

The editorโ€™s routes are as follows:

 // 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' } ] } 

And the last part for QueryEditor is as follows:

 // app/editor/query/query-editor.routes.ts { path: "", component : QueryEditorHostComponent, children : [ { path: 'create', component : QueryCreateComponent }, { path: ':queryId', component : QueryEditorComponent } ] } 

However, for this to work, the general Editor must import and export QueryEditor , and QueryEditor must export QueryCreateComponent and QueryEditorComponent , since they are visible with the import. Otherwise, you will get errors in the lines Component XYZ is defined in multiple modules .

Note that lazy loading also works great with this setting, in which case child routes should not be imported, of course.

+35
Aug 15 '16 at 9:53 on
source share

I had the same problem.

The answer here is pretty good using loadChildren:

  { path: 'mypath', loadChildren : () => myModule } 

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

+21
Oct 22 '16 at 10:10
source share

I found a way to solve this problem. Basically, I define my routes the way I'm used to, but this time at the top level of the child. For example, my admin route:

 const AdminRoutes: Routes = [ { path: 'admin', component: AdminComponent, children: [ ...setupRoutes ] } ] export const adminRouting = RouterModule.forChild(AdminRoutes) 

My configuration routes file is imported from a subzone that defines its own routes, including more children. The trick is that this file exports the Routes object, not the result of RouterModule.forChild.

After this installation, I removed the routes of the child and child objects from the definitions of the submodules. Then I had to export all the components used in the routes from each of the submodules, like the Marcus mentioned above. As soon as I did this, the routes started working the way I wanted them.

I donโ€™t think I really like this solution, since my parent module knows too much about the routes of the child modules. But at least it's an easy way to get around it for RC5, and it doesn't leak all my components everywhere. I will continue and answer Mark as an answer, since he set me on the right path.

+1
Aug 18 '16 at 22:05
source share

I got this to work, and if you really need to display all the parent components in a hierarchy, I think my solution is much more elegant.

The key to understanding my approach is that all routes, no matter how deeply embedded in the modules, are added to the root module. A quick example, let's say we have DepartmentModule and EmployeeModule that we would like to use to use this URL

 /department/1/employee/2 

at this moment we will see the details of employee 2. Setting up routes for department in department.routing.ts and employee in employee.routing.ts will not work as we planned, and you will notice that you can go to

 /employee/2 

from the root component, and

 /department/1/employee/2 

Failure (route not found). A typical route configuration in this scenario would look like this:

 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 } ]} ]; 

and EmployeeModule will be imported using DepartmentModule . Now, as I said, this does not work, unfortunately.

However, in just one change, this will be:

 export const employeeRoutes: Routes = [ { path: 'department/:id/employee', component: EmployeeComponent, children: [ { path: '', component: EmployeesComponent }, { path: ':id', component: EmployeeDetailsComponent } ]} ]; 

The catch is that the DepartmentModule no longer actively involved as soon as you navigate to the employee URL, but you can still access each parameter from 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']); } } 

I wonder if this should be an official approach, but so far it works for me until the next exploding change to the Angular 2 team.

+1
Sep 22 '16 at 3:52
source share

I think 2.0.0 rc5 is not interested now. But it works in Angular 4, maybe earlier.

 @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 {} 

Consider on loadChildren: () => {...} . This is not lazy loading.

See feat for more details : NgModules sans Lazy hierarchy support Loading

+1
Apr 2 '17 at 19:45
source share

When you use ngModules and RC5, the routing configuration of your parent module does not need to know anything about routing child modules. Here you need to define routes for your parent module. In addition, you need to import the child module into the parent module. In the child module, you must define your routes as follows:

 export const childRoutes: Routes = [ { path: 'someChild', component: SomeChildComponent, children: [ { path: '', component: SomeChildSubComponent1 }, { path: 'comp1', component: SomeChildSubComponent1 }, { path: 'comp2', component: SomeChildSubComponent2 } ] } ]; 

This will allow you to have the URL / someParent / someChild / comp1 - and the components are displayed in the corresponding router-exit. Note: you need to declare a component for an empty path. Otherwise, you cannot go to the children.

0
02 Sep '16 at 8:11
source share

Use loadChildren . This is normal. But when you restart the build process, you will get a build error. You must map the exported character to loadChildren .

 import { ChildModule } from './child/child.module'; export function childRouteFactory() { return ChildModule; } ... { path: 'child', loadChildren: childRouteFactory } ... 
0
Apr 14 '17 at 0:52
source share



All Articles