I have a main router-outlet
, which is used to display a login screen (/login
) and the main content screen(which is shown after login) (/main
).
Once the user is on content screen, I want to show a nav-bar on top, with 2 options(say, 'Overview', 'Insights'). This nav-bar is common for OverviewComponent
and InsightsComponent
Below this nav-bar, I want to show another router-outlet, which would load OverviewComponent
or InsightsComponent
, based on what user clicks in nav-bar. If I give '/overview' and /'insights' as the route, it would directly show me the respective component, but not the nav-bar.
Following is my current routing config (this is not right):
const appRoutes: Routes = [
{ path: 'main', component: MainComponent},
{ path: 'overview', component: OverviewComponent},
{ path: 'insights', component: InsightsComponent },
{ path: 'login', component: LoginComponent },
{ path: '',
redirectTo: '/login',
pathMatch: 'full'
},
{ path: '**', component: PageNotFoundComponent }
];
Kindly let me know if we can achieve this in angular2 angular4. I'm using following version:
"@angular/core": "^4.0.0"
"@angular/router": "^4.0.0"
"@angular/cli": "1.0.1"
******************Attempt 2 - Still not working******************
const appRoutes: Routes = [
{ path: 'main',
children: [
{ path: '', component: MainComponent },
{ path: 'overview', component: OverviewComponent },
{ path: 'insights', component: InsightsComponent },
]
},
{ path: 'login', component: LoginComponent },
{ path: '',
redirectTo: '/login',
pathMatch: 'full'
},
{ path: '**', component: PageNotFoundComponent }
];
*******Attempt 2 - Sudo Code with all components - Still not working*******
//app.component.html
<router-outlet></router-outlet>
//app.module.ts
const appRoutes: Routes = [
{ path: 'main',
children: [
{ path: '', component: MainComponent },
{ path: 'overview', component: OverviewComponent },
{ path: 'insights', component: InsightsComponent },
]
},
{ path: 'login', component: LoginComponent },
{ path: '',
redirectTo: '/login',
pathMatch: 'full'
},
{ path: '**', component: PageNotFoundComponent }
];
//login.component.html
<div class="text-center vertical-center">
<form>
<div class="horizontal">
<label for="">Email</label>
<input class="form-control" type="text" name="" value="">
</div>
<div class="horizontal">
<label for="">Password</label>
<input class="form-control" type="password" name="" value="">
</div>
<button class="btn btn-primary" (click)="navigate()">Login</button>
</form>
</div>
//login.component.ts
navigate() {
this.router.navigate(['./main']);
}
//main.component.html
<app-header></app-header>
<router-outlet></router-outlet>
//app.header.html
<ul class="nav navbar-nav">
<li class=""><a routerLink="/main/overview" routerLinkActive="active">OVERVIEW</a></li>
<li class=""><a routerLink="/main/insights" routerLinkActive="active">INSIGHTS</a></li>
</ul>
//overview.html
<p>This is overview section</p>
//insights.html
<p>This is insights section</p>
********Attempt 3 - Working**********
const appRoutes: Routes = [
{ path: 'main', component: MainComponent,
children: [
{ path: '', component: MainComponent },
{ path: 'overview', component: OverviewComponent },
{ path: 'insights', component: InsightsComponent },
]
},
{ path: 'login', component: LoginComponent },
{ path: '',
redirectTo: '/login',
pathMatch: 'full'
},
{ path: '**', component: PageNotFoundComponent }
];
So if I get the question right you want to have login screen initially and after the user logs in, you want him to see /main where navigation is shown. Both login screen and main application should have a different layout.
We have a similar case and using LayoutComponent. Here's simplified example.
So the flow would be like so:
Hope that helps.
EDIT: Updated sickelap/ng-starter repository with example app that has:
I think i gather what you are trying to achieve. Can i recommend that you use a variable to mimic some kind of state change, and assign that to the component view. have your app.component.html only contain a router outlet. create a new main.component.html that replicates the existing component.html
replace the href in the with *
(click)="handleChange(<linkValue>)'"
So each link would look as below.
<ul class="nav navbar-nav"> <li class=""><a href="/main/overview">OVERVIEW</a></li>
handleChange
method: declare the currentLink -public currentLink string;
// or public currentLink: string = '<a default value>';
public handleChange(link: string) { this.currentLink = link; }
create a view.component.
example selector
<view [link]='currentLink'></view>
give the view component an
@Input() public link: string;
<div id="overview" *ngIf="link = 'overview'">overview content</div>
<div id="main" *ngIf="link = 'main'">overview content</div>
You can then refactor those into seperate child components.
Overview: You are making the app-header a global component that handles a 'link' variable. I would recommend taking a look into ngRx or general app-state methods. As this can be a great way to manage UI.