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!
Use
loadChildren
. That's OK. But when you restart the build process, you will get the build error. You should match the exported symbol to theloadChildren
.I got this to work as well and unless you actually need to render all parent components in the hierarchy I think my solution is far more elegant.
The key to understanding my approach is that all routes, no matter how deeply nested in modules are added to the root module. Quick example, let's say we have a
DepartmentModule
and anEmployeeModule
which we'd like to navigate to using this URLat which point we'd see employee 2's details. Configuring routes for
department
indepartment.routing.ts
andemployee
inemployee.routing.ts
will not work the way we intended and you'll notice that you can navigate tofrom the root component, while
will crash (route not found). A typical route configuration in this scenario would look like this:
and
EmployeeModule
would be imported byDepartmentModule
. Now, like I said, that doesn't work unfortunately.However, with just a single change it will:
The catch is, that
DepartmentModule
is not taking an active part anymore as soon you navigate to anemployee
URL, but you still can access every parameter from theActivatedRoute
:I wonder if this is supposed to be the official approach, but for now this works for me until the next breaking change from the Angular 2 team .
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:
Routes
for every module you want to route. Do not import any of theRouterModule.forChild()
in the child modules.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:
/
)editor/:projectId
)query/:queryId
)page/:pageId
)about
)The following definitions work for me for the
/editor/:projectId/query/:queryId
path:The editor routes look like this:
And the final part for the QueryEditor looks like this:
However, to make this work, the general
Editor
needs to import and export theQueryEditor
and theQueryEditor
needs to exportQueryCreateComponent
andQueryEditorComponent
as these are visible with the import. Failing to do this will get you errors along the lines ofComponent 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.
I think 2.0.0 rc5 isn't interested now. But is is worked in Angular 4, may be early too.
Take in account on
loadChildren: () => {...}
. It is not the lazy loading.See for details feat: Support NgModules hierarchy sans Lazy Loading
I had the same problem.
The answer here is pretty good using loadChildren :
https://github.com/angular/angular/issues/10958
When you are using ngModules and RC5, the routing configuration of your parent module does not need to know anything about the child modules routing. You only have to define the routes for your parent module here. Furthermore you have to import the child module into your parent module. In the child module you have to define your routes this way:
This will let you have a url like /someParent/someChild/comp1 - and the components are displayed in their corresponding router-outlet. Please note: You HAVE TO declace a component for the empty path. Otherwise you are not able to navigate to you children.