I've been playing around with the Angular 2 webpack starter found here, which has a ton of useful examples. I've run into an issue with routing, though. I've removed a few of the modules & added one of my own, which contains children (I'm still not sure if using child modules or child components would be best practice- I'm currently trying this with components).
My objective is to be able to switch between top-level modules as normal (Home
and About
, in this case), but after loading my Home
module, swap between multiple child components (or modules, if that's better supported) within the Home
module's template.
I'm trying to use another <router-outlet>
within Home
- I've tried naming it & using the outlet
paramter in the Home
module routing definition, but clicking links to load within Home
doesn't currently work. Code below:
This is my current app structure (with most of the extra webpack stuff left out):
app
|-app.component.ts (template contains router-outlet)
|-app.module.ts
|-app.routes.ts
|-about
|-about.component.ts
|-about.component.html
|-home
|-home.module.ts
|-home.component.ts
|-home.component.html (contains router outlet for children)
|-home.routes.ts
|-signup
|-signup.component.ts
|-signup.component.html
|-login
|-login.component.ts
|-login.component.html
This is my app.component, which is almost the same as it starts in the starter repo- I just added a link to my own module & removed the others:
app.component.ts
import {
Component,
OnInit,
ViewEncapsulation
} from '@angular/core';
@Component({
selector: 'app',
encapsulation: ViewEncapsulation.None,
styleUrls: [
'./app.component.css'
],
template: `
<nav>
<a [routerLink]=" ['./home'] " routerLinkActive="active">
Home
</a>
<a [routerLink]=" ['./about'] " routerLinkActive="active">
About
</a>
</nav>
<main>
<router-outlet></router-outlet>
</main>
`
})
export class AppComponent implements OnInit {
constructor(
public appState: AppState
) {}
public ngOnInit() {
console.log('Initial App State', this.appState.state);
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import {
NgModule,
ApplicationRef
} from '@angular/core';
import {
removeNgStyles,
createNewHosts,
createInputTransfer
} from '@angularclass/hmr';
import {
RouterModule,
PreloadAllModules
} from '@angular/router';
/*
* Platform and Environment providers/directives/pipes
*/
import { ENV_PROVIDERS } from './environment';
import { ROUTES } from './app.routes';
// App is our top level component
import { AppComponent } from './app.component';
import { APP_RESOLVER_PROVIDERS } from './app.resolver';
import { AppState, InternalStateType } from './app.service';
import { AboutComponent } from './about';
import { HomeModule } from './home';
import { XLargeDirective } from './home/x-large';
// app services needed globally
import { AuthenticationService, UserService, AlertService } from './shared';
import '../styles/styles.scss';
import '../styles/headings.css';
// Application wide providers
const APP_PROVIDERS = [
...APP_RESOLVER_PROVIDERS,
AppState
];
type StoreType = {
state: InternalStateType,
restoreInputValues: () => void,
disposeOldHosts: () => void
};
/**
* `AppModule` is the main entry point into Angular2's bootstraping process
*/
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
AboutComponent,
NoContentComponent,
XLargeDirective
],
imports: [ // import Angular's modules
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot(ROUTES, { useHash: true, preloadingStrategy: PreloadAllModules })
],
providers: [ // expose our Services and Providers into Angular's dependency injection
ENV_PROVIDERS,
APP_PROVIDERS,
UserService,
AuthenticationService,
AlertService
]
})
export class AppModule {
constructor(
public appRef: ApplicationRef,
public appState: AppState
) {}
}
app.routes.ts
import { Routes } from '@angular/router';
import { HomeModule } from './home';
import { AboutComponent } from './about';
import { DataResolver } from './app.resolver';
export const ROUTES: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'about', component: AboutComponent },
{ path: 'home', loadChildren: './home#HomeModule' },
{ path: '**', redirectTo: '/home', pathMatch: 'full' }
];
Navigation to my Home module works fine- I think the issue is the routing within it. This is the Home module, component, & routing.
home.module.ts
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { routes } from './home.routes';
import { HomeComponent } from './home.component';
import { SignupComponent } from './signup/signup.component';
import { LoginComponent } from './login/login.component';
console.log('`Home` loaded');
@NgModule({
declarations: [
// Components / Directives/ Pipes
HomeComponent,
SignupComponent,
LoginComponent
],
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(routes),
],
})
export class HomeModule {
public static routes = routes;
}
home.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'home',
styleUrls: [ './home.component.css' ],
templateUrl: './home.component.html'
})
export class HomeComponent implements {
}
home.component.html
<h1>Home</h1>
<div>
<h2>Hello from home module</h2>
</div>
<span>
<a [routerLink]=" ['./signup'] ">
Sign Up
</a>
</span>
<span>
<a [routerLink]=" ['./login'] ">
Login
</a>
</span>
<router-outlet name="aux"></router-outlet>
<div>
<h2>Bottom info</h2>
</div>
home.routes.ts
import { HomeComponent } from './home.component';
import { SignupComponent } from './signup/signup.component';
import { LoginComponent } from './login/login.component';
export const routes = [
{ path: '',
component: HomeComponent,
children: [
{
path: 'signup',
component: SignupComponent,
outlet: 'aux'
},
{
path: 'login',
component: LoginComponent,
outlet: 'aux'
}
] }
];
The current behavior is that nothing happens when I click one of the links for Signup
or Login
- no errors, but the components are not loaded at the aux
router-outlet, either.
I've tried configuring Signup
as a module, but that hasn't worked for me yet either- I think there's some extra config that I don't understand, and figured treating the children as components would help me understand the basic required routing.
From researching this question, it seems like multiple router-outlets hasn't been well supported, especially using them with the router-link
syntax, until around RC5. This recent answer to a similar question suggests that it does work now, but similar syntax isn't working for me.
Is it an issue to have the router-outlets
nested? Should I be defining the Signup
and Login
components as modules instead? Or is there some other problem altogether with the way I've defined the routing, perhaps at the uppermost AppModule level?
EDIT
I've added app.module.ts
to the question. Additionally, after looking at the base configuration of the starter project I used, it seems like using child modules can simplify things- specifically the barrel
module (viewable here) has a child-barrel
module, and it's loaded into the router-outlet
present in the barrel.component
template. If there was a child-barrel-2
module at the same level, this would be the sort of thing I'm looking for.
I also found this question, where the top answer states that
Modules are recommended
Should I be trying to mimic the structure of the starter, where the parent-child relationship is accomplished by using modules?
Yes you can as said by @tomer above. i want to add some point to @tomer answer. firstly you need to provide name to the router-outlet where you want to load the second routing view in your view. (aux routing angular2.)
Descriptionlink Using named outlets and secondary routes, you can target multiple outlets in the same RouterLink directive.
Yes! We can use multiple router-outlets in same template by configuring our routers and simply add the router-outlet name. You can see in the example.
Why are you using '.' in front of '/' in <a [routerLink]=" ['./signup'] ">
Try removing it.
.what is your base href
EDIT
Why don't you try something like this in template.
<a [routerLink]="[{outlets: {primary: 'home', aux: 'signup'}}]">signup </a>
and below code in routes config
{path: 'signup', component: signUpComponent, outlet:"aux"}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With