My app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'updateBooking', loadChildren: () => import('./update-booking/update-booking.module').then(m => m.UpdateBookingModule) },
{ path: 'booking', loadChildren: () => import('./booking/booking.module').then(m => m.BookingModule) }
];
#NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }
lazy loaded Booking module's routing:
const routes: Routes = [
{ path: '', redirectTo: 'bookingdashboard' },
{
path: 'bookingdashboard', component: BookingDashboardComponent,
children: [
{ path: '', redirectTo: 'associateinfo' },
{
path: 'associateinfo', component: AssociateInfoComponent
},
{
path: 'agenda', component: AgendaComponent
},
{
path: 'zone', component: ZoneComponent
},
]
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class BookingRoutingModule { }
I am on associate info page with url http://localhost:4200/booking/bookingdashboard/associateinfo
From this page when I try to navigate to agenda page using this._route.navigate(['../agenda' ]); I am getting error Cannot match any routes. URL Segment: 'agenda'
Error: Cannot match any routes. URL Segment: 'agenda'
However If I try to navigate from HTML file using [routerLink]="[ '../agenda']" its navigating to agenda page
You are navigating to only component specific route path, you should follow route as module-path/component-path
this._route.navigate(['booking/bookingdashboard/agenda' ]);
try
this._route.navigate(['/booking/bookingdashboard/agenda']);
After the link parameters array, add an object with a relativeTo
property set to the ActivatedRoute. The router then calculates the
target URL based on the active route's location.
constructor(private _router: Router, private route: ActivatedRoute){}
this._router.navigate(['../agenda'], { relativeTo: this.route })
In app.module.ts I load 2 lazy modules like this
const appRoutes: Routes = [
{ path: 'anonym', loadChildren: './anonym/anonym.module#AnonymModule' },
{ path: 'user', loadChildren: './user/user.module#UserModule', canActivate: [AuthGuard] }
];
In app.component.html I can write some base html. My question - is there any way to have base html for my UserModule?
I have tried to create user.component.ts and load it like in app.module.ts
import { UserComponent } from './user.component';
#NgModule({
declarations: [UserComponent],
bootstrap: [UserComponent]
});
but it's not show me user.component.html
In your user module define a base route with an empty path, and then define the sub-paths as children.
const ROUTES: Routes = [
{
path: '',
component: UsersComponent,
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'login'
}, {
path: 'login',
component: LoginComponent
}, {
path: 'logout',
component: LogoutComponent
}
]
}
];
The UsersComponent will now be used as a base component, and if you navigate to just /users it will redirect to the /users/login path.
Make sure your UsersComponent has a template with <router-outlet></router-outlet> so the child routes.
#NgModule({
imports: [
RouterModule.forChild(ROUTES)
],
exports: [
RouterModule
]
})
export class UsersModule {
}
I have an Angular 2 app. The main screen (app?) looks like this...
When you click items in the top menu routerLinks, new Components load into the main view router outlet. One of those links loads up an new "Admin" Module/Component with it's own routes and new router outlet...
Then when you click the routerLinks in the left nav, new admin Components will load in the new router outlet.
But...
Angular 2 does not allow more than 1 router outlet. So clicking on any routerLink in left nav simply replaces the entire inital router outlet view.
I've seen some SO posts (older, maybe deprecated) on using "bootstrap" to load subsequent Components, but I can't get that to work. I can't even import { bootstrap } from 'anywhere at all, nothing works'. So maybe that's not the way to do this.
How can I get the Admin sub app part to work?
Thank you very, very much for sharing your Angular 2 expertise :-)
EDIT: Trying suggested solutions below. No matter where I put the routes, in the base app.routes.ts or in the sub-app admin.routes.ts, no matter how I format the routerLinks, I keep getting this error...
EDIT AGAIN: Here is the code in the routers and the template...
<!--
============================================================================
/src/app/component/admin/admin.component.html
-->
<!-- Row for entire page columnar dispaly -->
<div class="row">
<!-- Column 1: Left navigation, links to all admin components -->
<div class="col col-md-4">
<app-admin-nav></app-admin-nav>
</div>
<!-- Column 2: Rows of records, click to edit -->
<div class="col col-md-8">
<router-outlet name="admin-app"></router-outlet>
</div>
</div>
// ============================================================================
// /src/app/app.routes.ts
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { AppComponent } from './app.component';
import { GameComponent } from './component/game/game.component';
import { HomeComponent } from './component/home/home.component';
import { LoginComponent } from './component/login/login.component';
import { PlayerComponent } from './component/player/player.component';
import { AuthGuard } from './service/auth/auth.service';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
import { AdminComponent } from './component/admin/admin.component';
// import { AdminWorldComponent } from './component/admin/world/admin-world.component';
// import { AdminModuleComponent } from './component/admin/module/admin-module.component';
// import { AdminRegionComponent } from './component/admin/region/admin-region.component';
export const router: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }
, { path: 'home', component: HomeComponent }
, { path: 'game', component: GameComponent, canActivate: [AuthGuard] }
, { path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
// , {
// path: 'admin', component: AdminComponent, canActivate: [AuthGuard],
// children: [
// { path: 'world', component: AdminWorldComponent, outlet: 'admin-app' },
// { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' },
// { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
// ]
// },
, { path: 'login', component: LoginComponent }
, { path: 'signup', component: SignupComponent }
, { path: 'login-email', component: EmailComponent }
, { path: 'players', component: PlayerComponent, canActivate: [AuthGuard] }
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
// ============================================================================
// /src/app/component/admin/admin.routes.ts
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { AdminComponent } from './admin.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
export const router: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent, outlet: 'admin-app' }
, { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' }
, { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
]
}
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
EDIT 3: Tried changing RouterModule.forRoot to RouterModule.forChild, sadly, same error :-/
EDIT 4: Converted routing to use 2 routing modules. Was hoping maybe that would make a difference, but same error.
New routers...
// ============================================================================
// /src/app/app-routing.module.ts
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AppComponent } from './app.component';
import { GameComponent } from './component/game/game.component';
import { HomeComponent } from './component/home/home.component';
import { LoginComponent } from './component/login/login.component';
import { PlayerComponent } from './component/player/player.component';
import { AuthGuard } from './service/auth/auth.service';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
import { AdminComponent } from './component/admin/admin.component';
export const appRoutes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }
, { path: 'home', component: HomeComponent }
, { path: 'game', component: GameComponent, canActivate: [AuthGuard] }
, { path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
// , {
// path: 'admin', component: AdminComponent, canActivate: [AuthGuard],
// children: [
// { path: 'world', component: AdminWorldComponent, outlet: 'admin-app' },
// { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' },
// { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
// ]
// },
, { path: 'login', component: LoginComponent }
, { path: 'signup', component: SignupComponent }
, { path: 'login-email', component: EmailComponent }
, { path: 'players', component: PlayerComponent, canActivate: [AuthGuard] }
];
#NgModule({
imports: [
RouterModule.forRoot(appRoutes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
// ============================================================================
// /src/app/admin/admin-routing.module.ts
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AdminComponent } from './admin.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
export const adminRoutes: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent, outlet: 'admin-app' }
, { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' }
, { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
]
}
];
#NgModule({
imports: [
RouterModule.forChild(adminRoutes)
],
exports: [
RouterModule
]
})
export class AdminRoutingModule { }
EDIT 5: IT'S WORKING!
Removed the routing modules, returned to exporting routes config per Tyler's suggestion. He is right, the routing modules do not work. Tyler worked with me a lot so I'm accepting his answer. Thank you Tyler for your help!
Here is how you can setup a parent app with it's own router-outlet, then on the parent click a link to load up a child app with it's own new router-outlet. The child app loads/replaces the parent app router-outlet.
There is really nothing special in the parent app module or routes. They're just how I had them before this post.
The important points to note, at least in my case today, do not use a name="" attrib in the child router-outlet. This will cause "Error: Cannot match any routes...". Do not use routing modules like I tried above, this also causes "Error: Cannot match any routes...". Do not use outlet: 'blah' in the routes, this also causes "Error: Cannot match any routes...". Make sure you set up the child route config children: [] exactly as you see below in admin.routes.ts. Also, note the RouterModule.forChild(router) in the child routes. These things fixed the issue for me today.
PARENT APP
// ============================================================================
// src/app/app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AngularFireModule } from 'angularfire2';
import { firebaseConfig } from '../environments/firebase.config';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
// import { AppRoutingModule } from './app-routing.module';
import { routes } from './app.routes';
// Components
import { AppComponent } from './app.component';
import { HomeComponent } from './component/home/home.component';
import { GameComponent } from './component/game/game.component';
import { PlayerComponent } from './component/player/player.component';
import { LoginComponent } from './component/login/login.component';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
// Admin Module
import { AdminModule } from './component/admin/admin.module';
// Services
import { AuthGuard } from './service/auth/auth.service';
import { AuthPlayerService } from './service/auth/auth-player.service';
import { MdbService } from './service/mongo/mdb.service';
import { PlayerMdbService } from './service/mongo/player-mdb.service';
#NgModule({
declarations: [
AppComponent
, HomeComponent
, GameComponent
, PlayerComponent
, LoginComponent
, SignupComponent
, EmailComponent
],
imports: [
BrowserModule
, FormsModule
, HttpModule
, AdminModule
, AngularFireModule.initializeApp(firebaseConfig)
, NgbModule.forRoot()
// , AppRoutingModule
, routes
],
providers: [
AuthGuard
, AuthPlayerService
, MdbService
, PlayerMdbService
],
bootstrap: [AppComponent]
})
export class AppModule { }
// ============================================================================
// /src/app/app.routes.ts
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { AppComponent } from './app.component';
import { GameComponent } from './component/game/game.component';
import { HomeComponent } from './component/home/home.component';
import { LoginComponent } from './component/login/login.component';
import { PlayerComponent } from './component/player/player.component';
import { AuthGuard } from './service/auth/auth.service';
import { SignupComponent } from './component/signup/signup.component';
import { EmailComponent } from './component/email/email.component';
import { AdminComponent } from './component/admin/admin.component';
export const router: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'game', component: GameComponent, canActivate: [AuthGuard] },
{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard] },
{ path: 'login', component: LoginComponent },
{ path: 'signup', component: SignupComponent },
{ path: 'login-email', component: EmailComponent },
{ path: 'players', component: PlayerComponent, canActivate: [AuthGuard] }
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
CHILD APP
// ============================================================================
// /src/app/admin/admin.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { CommonModule } from '#angular/common';
import { routes } from './admin.routes';
// import { AdminRoutingModule } from './admin-routing.module';
import { AdminComponent } from './admin.component';
import { AdminRecsComponent } from './admin-recs.component';
import { AdminFormComponent } from './admin-form.component';
import { AdminNavComponent } from './admin-nav.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
#NgModule({
imports: [
CommonModule
, FormsModule
// , AdminRoutingModule
, routes
]
, declarations: [
AdminComponent
, AdminNavComponent
, AdminRecsComponent
, AdminFormComponent
, AdminWorldComponent
, AdminModuleComponent
, AdminRegionComponent
]
, schemas: [CUSTOM_ELEMENTS_SCHEMA]
, exports: [
AdminRecsComponent
, AdminFormComponent
, AdminNavComponent
// , AdminWorldComponent
// , AdminModuleComponent
// , AdminRegionComponent
]
// , bootstrap: [AdminComponent]
})
export class AdminModule { }
// ============================================================================
// /scr/app/admin/admin.routes.ts
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { AdminComponent } from './admin.component';
import { AdminWorldComponent } from './world/admin-world.component';
import { AdminModuleComponent } from './module/admin-module.component';
import { AdminRegionComponent } from './region/admin-region.component';
export const router: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent },
{ path: 'module', component: AdminModuleComponent },
{ path: 'region', component: AdminRegionComponent },
]
}
];
export const routes: ModuleWithProviders = RouterModule.forChild(router);
Not sure where you heard that Angular2 does not allow more than 1 router-outlet. I am using several in a large application.
Your main app.component will have a router-outlet to handle the root routes. If one of your routes lazy-loads the Admin Module, that admin module will have it's root component that contains the side menu bar and a router-outlet for all the children routes.
Example:
//app.routes
export const ROUTES: Routes = [
// Main redirect
{ path: '', component: MainViewComponent },
{
path: 'admin',
loadChildren: './admin/admin.module#AdminModule'
}
]
Your MainViewComponent can contain the top navbar and a router-outlet.
Then the Admin router config may look like this:
export const routes: Routes = [
{
path: '',
component: AdminComponent,
children: [
{ path: '', component: Component1},
{ path: 'component2', component: Component2}
]
}
];
Your root component in the Admin module may contain the side bar menu and a router-outlet to show the children components.
You can also do named router-outlets. An example of this is having two router-outlets side-by-side:
<router-outlet></router-outlet>
<router-outlet name="popup"></router-outlet>
Your router config would look like this:
{
path: 'compose',
component: ComposeMessageComponent,
outlet: 'popup'
},
And you would use it like this:
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
Or clear the content with this:
this.router.navigate([{ outlets: { popup: null }}]);
See the docs or this article for more details.
Hope that helps.
Edit
When using the route config for a lazily loaded child, make sure your route configs are loaded properly in your modules. The root route config will be loaded in the root AppModule with RouterModule.forRoot(routes) and the child routes are in the Child module with RouterModule.forChild(routes).
Your route config and modules need to look like this(don't create a separate module just to hold routing config):
//Admin Routes
export const adminRoutes: Routes = [
{
path: 'admin', component: AdminComponent,
children: [
{ path: 'world', component: AdminWorldComponent, outlet: 'admin-app' }
, { path: 'module', component: AdminModuleComponent, outlet: 'admin-app' }
, { path: 'region', component: AdminRegionComponent, outlet: 'admin-app' }
]
}
];
//Admin Module:
import { adminRoutes } from './admin.routes';
#NgModule({
imports: [
...
RouterModule.forChild(adminRoutes),
]
...
//App Routes(lazy load Admin module)
export const appRoutes: Routes = [
{ path: 'admin', loadChildren: './admin/admin.module#AdminModule' },
....
//App Module
import { appRoutes } from './app.routes';
#NgModule({
imports: [
...
RouterModule.forRoot(appRoutes),
]
...
Hope that helps.
Yes, there is a way to do this.
You need to name your router outlet like:
<router-outlet name="child1"></router-outlet>
<router-outlet name="child2"></router-outlet>
And inside your router you need to define what router-outlet should route use:
{
path: 'home', // you can keep it empty if you do not want /home
component: 'appComponent',
children: [
{
path: '',
component: childOneComponent,
outlet: 'child1'
},
{
path: '',
component: childTwoComponent,
outlet: 'child2'
}
]
}
Original post:
Angular2 multiple router-outlet in the same template
I want the base path http://localhost:3000/ or / to redirect to /wiki in my app.
My app.routing.ts file
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { CategoryComponent } from './category/category.component';
import { EntityComponent } from './entity/entity.component';
#NgModule({
imports: [
RouterModule.forChild([
{ path: '', redirectTo: '/wiki', pathMatch: 'full' },
{ path: 'wiki/category/:id', component: CategoryComponent },
{ path: 'wiki/entity/:id', component: EntityComponent }
])
],
})
export class AppRoutingModule { }
I assumed this was enough: { path: '', redirectTo: '/wiki', pathMatch: 'full' }
Also tried { path: '/', redirectTo: '/wiki', pathMatch: 'full' }
Anyone see what I'm missing?
I also tried adding the HomeComponent into the path for /wiki. Going to localhost:3000 still did not redirect to /wiki, and when I manually typed and went to /wiki I got the following error:
Error: Invalid configuration of route '': redirectTo and component cannot be used together
at validateNode (/Users/leongaban/Projects/TickerTags/wikitags/dist/server/index.js:54088:15)
at Array.forEach (native)
Code
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { CategoryComponent } from './category/category.component';
import { EntityComponent } from './entity/entity.component';
import { HomeComponent } from './home/home.component';
#NgModule({
imports: [
RouterModule.forChild([
{ path: '', redirectTo: '/wiki', pathMatch: 'full', component: HomeComponent },
{ path: 'wiki/category/:id', component: CategoryComponent },
{ path: 'wiki/entity/:id', component: EntityComponent }
])
]
})
export class AppRoutingModule { }
As #GünterZöchbauer said, you need to define the path you'll redirect to. Here's a snippet.
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { CategoryComponent } from './category/category.component';
import { EntityComponent } from './entity/entity.component';
#NgModule({
imports: [
RouterModule.forChild([
{ path: '', redirectTo: '/wiki', pathMatch: 'full' },
{ path: 'wiki/category/:id', component: CategoryComponent },
{ path: 'wiki/entity/:id', component: EntityComponent },
{ path: '/wiki', component: HomeComponent }
])
],
})
export class AppRoutingModule { }
I was able to fix the redirect problem in the Node part of the app. Still will wait to see if there is a better Angular client fix for this.
I just added the path to / and redirected it to /wiki:
app.get('/', function(req, res) {
return res.redirect('/wiki');
});
app.get('*', function(req, res) {
res.setHeader('Content-Type', 'application/json');
var pojo = { status: 404, message: 'No Content' };
var json = JSON.stringify(pojo, null, 2);
res.status(404).send(json);
});