Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to route to a Module as a child of a Module - Angular 2 RC 5

I am in the process upgrading an application I'm working on to the latest Angular 2 release candidate. As part of this work I am attempting to use the NgModule spec and migrating all of the parts of my application to modules. For the most part, this has gone very well with the exception of an issue with routing.

"@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 app is built as a composition of modules, with several modules being glued together as children of a parent module. For example, I have an Admin Module that consists of a Notifications Module, a Users Module, and a Telphony Module (for example). The routes to these modules should look like...

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

In the earlier release of the router, this was easy to accomplish using "children"

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

In another file, as part of the sub-modules, I'd define the individual module routes as well i.e.

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

This all worked very well. In the process of upgrading to Modules, I moved everything into their own individual routing files instead so now these two look 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 of that in place, I have a UsersModule which imports the userRouting, and then an AdminModule that imports the adminRoutes and the UsersModule. My thought was that since UsersModule is a child of AdminModule, the routing would work the way it used to. Unfortunately, it doesn't so I end up with a users route that is just

/users/new-user  

instead of

/admin/users/new-user 

Further, because of this, the new-user component isn't loaded into the router outlet of my admin component which throws off the styling and navigation of my application.

I can't for the life of me come up with how to reference the routes of my UserModule as children of my AdminModule. I've tried doing this the old way and get errors about the routes being in two Modules. Obviously since this is newly released, the documentation around some of these cases is a bit limited.

Any help anyone can provide would be greatly appreciated!

like image 618
John Ackerman Avatar asked Aug 10 '16 17:08

John Ackerman


People also ask

What is child route in Angular?

With child routes, you can have a component-like structure defined for the routes in your app. It is critical as there are views that the user should not be able to access unless they are in a particular view. This way, the structure becomes tree-like, just like the structure of components.

How do you use the parent module component in a child module?

You should export the components of the parent module, you want to use in the child module. Then import the parent module in the child module. Show activity on this post. It would have been great , if you can share the code and the specified the error you are getting.

What would you use in Angular 2 to define route?

Instead of “href” attribute of anchor tag, we use the “routerLink” attribute of Angular. The routerLink attribute allows us to link to a specific route of the Application.


2 Answers

Okay, after fiddling around with this for the better part of the weekend I got it running on my end. What worked for me in the end was to do the following:

  • Export all Routes for every module you want to route. Do not import any of the RouterModule.forChild() in the child modules.
  • Export every component that is visible from the childs route definitions in the childs module definition.
  • Import (meaning the Typescript import keyword) all child routes as usual and use the ... operator to incorporate these under the correct path. I couldn't get it to work with the child-module defining the path, but having it on the parent works fine (and is compatible to lazy loading).

In my case I had three levels in a hierarchy like this:

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

The following definitions work for me for the /editor/:projectId/query/:queryId path:

// 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 routes look like this:

// 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 final part for the QueryEditor looks like this:

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

However, to make this work, the general Editor needs to import and export the QueryEditor and the QueryEditor needs to export QueryCreateComponent and QueryEditorComponent as these are visible with the import. Failing to do this will get you errors along the lines of Component XYZ is defined in multiple modules.

Notice that lazy loading also works fine with this setup, in that case the child-routes shouldn't be imported of course.

like image 62
Marcus Riemer Avatar answered Oct 11 '22 10:10

Marcus Riemer


I had the same problem.

The answer here is pretty good using loadChildren :

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

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

like image 35
Jklf Avatar answered Oct 11 '22 10:10

Jklf