angular - Angular2: Bruke ruter, hvordan vise navigasjonsfeltet etter å ha logget inn?
Jeg prøver å vise navigasjonslinjen, når brukeren lykkes med det.
For eksempel:
Hvordan endre "showMenu"-egenskapen i "AppComponent" inne i "LoginComponent"? Viktig: Jeg bruker ruter.
app.ts:
@Component({
selector: 'app',
template: `<div *ngIf="showMenu">
<fnd-menu-nav></fnd-menu-nav>
</div>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES, MenuNavComponent]
})
@RouteConfig([
{ path: '/login', name: 'Login', component: LoginComponent, useAsDefault: true },
{ path: '/welcome', name: 'Welcome', component: WelcomeComponent }
])
export class AppComponent {
public showMenu : boolean;
}
login.component.ts:
@Component({
selector: 'fnd-login',
templateUrl: './fnd/login/components/login.component.html',
providers: [LoginService]
})
export class LoginComponent {
/* .. other properties */
constructor(private _router: Router, private _loginService: LoginService ) {
}
/* .. other methods */
/* .. other methods */
private onLoginSuccessfully(data : any) : void {
/* --> HERE: Set showMenu in AppComponent to true. How? */
this._router.navigate(['Welcome']);
}
}
Eller er ikke dette designet den beste måten å løse det på?
Svar #1
Jeg gjorde nylig noe lignende, og her er hvordan jeg gjorde det. Først må du opprette en NavBarComponent på roten av appen din. Og i NavBarComponent refererer du til (det jeg kaller) en GlobalEventsManager, som er en tjeneste du injiserer der du trenger den.
Her er et blikk på GlobalEventsManager:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { Observable } from "rxjs/Observable";
@Injectable()
export class GlobalEventsManager {
private _showNavBar: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public showNavBarEmitter: Observable<boolean> = this._showNavBar.asObservable();
constructor() {}
showNavBar(ifShow: boolean) {
this._showNavBar.next(ifShow);
}
}Nå injiserer du GlobalEventsManger-tjenesten i login-komponenten din (noe slikt som dette)
import {GlobalEventsManager} from "./../GlobalEventsManager";
@Component({
selector: 'fnd-login',
templateUrl: './fnd/login/components/login.component.html',
providers: [LoginService]
})
export class LoginComponent {
/* .. other properties */
constructor(private _router: Router, private _loginService: LoginService, private globalEventsManager: GlobalEventsManager) {
}
/* .. other methods */
/* .. other methods */
private onLoginSuccessfully(data : any) : void {
/* --> HERE: you tell the global event manger to show the nav bar */
this.globalEventsManger.showNavBar(true);
this._router.navigate(['Welcome']);
}
}I din NavBarComponent abonnerer du på showNavBar Event Emitter:
import {Component, OnInit} from "@angular/core";
import {GlobalEventsManager} from "../GlobalEventsManager";
@Component({
selector: "navbar",
templateUrl: "app/main/topNavbar/TopNavbar.html"
})
export class TopNavbarComponent {
showNavBar: boolean = false;
constructor(private globalEventsManager: GlobalEventsManager) {
this.globalEventsManager.showNavBarEmitter.subscribe((mode)=>{
this.showNavBar = mode;
});
}
}bruk *ngIf="showNavBar" i mal-HTMLen for å skjule/vis Nav-baren.
Din app-komponent ser da omtrent slik ut:
@Component({
selector: 'app',
template: `<navbar></navbar>
<router-outlet></router-outlet>
`
})
export class AppComponent {
//This doesn't belong here --> public showMenu : boolean;
}Også må GlobalEventsManager registreres når du starter appen:
import { GlobalEventsManager } from './GlobalEventsManager';
import { TopNavbarComponent } from './TopNavbarComponent';
@NgModule({
bootstrap: [App],
declarations: [
App,
TopNavbarComponent
],
imports: [
BrowserModule
],
providers: [GlobalEventsManager]
})
export class AppModule {
}Det burde holde.
OPPDATERING: Jeg har oppdatert dette svaret for å gjenspeile den mer aksepterte måten å bruke hendelser utenfor en komponent, dvs. i en tjeneste; som innebærer å bruke BehaviorSubject/Observable i stedet for EventEmitter
Svar #2
Faktisk finnes det en helt annen tilnærming som ikke bruker noen av hendelsesutløserne/lytterne. Jeg har ingenting imot hendelsene, og jeg bruker begge tilnærmingene (den nedenfor og @brando sin) i henhold til de spesifikke prosjektbehovene/kompleksiteten.
Metoden: vi har 2 applikasjonsmoduler (områder): offentlig (som ikke har navigasjonslinje) og beskyttet (den som har en).
Offentlig modul inneholder alle offentlige ruter:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { RegistrationComponent } from './registration/registration.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{ path: 'login', component: LoginComponent },
{ path: 'registration', component: RegistrationComponent },
{ path: 'reset-password', component: ResetPasswordComponent }
])
],
declarations: [
LoginComponent,
RegistrationComponent,
ResetPasswordComponent
]
})
export class PublicModule { }
Dette er det du allerede burde ha, det er ingenting uvanlig her.
Så har vi et vernet område
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { NavbarWrapperComponent } from './navbar-wrapper/navbar-wrapper.component';
import { UserProfileComponent } from './user-profile/user-profile.component';
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{ path: '', redirectTo: '/login', pathMatch: 'full' }, // point 1
{
path: '', // point 2
component: NavbarWrapperComponent, // point 3
children: [
{ path: 'profile', component: UserProfileComponent }
]
}
])
],
declarations: [
NavbarWrapperComponent,
UserProfileComponent
]
})
export class ProtectedModule { }
og her starter magien.
Først av alt, vær oppmerksom på punkt 1:
{ path: '', redirectTo: '/login', pathMatch: 'full' },
Vi trenger dette her. Hvis vi legger det til i AppModule, vil det bli ignorert. Det er ingenting avgjørende her, det kan faktisk være mer logisk å ha denne omdirigeringen i den beskyttede modulen.
Punkt 2 lar oss videresende alle barnrutene til NavbarWrapperComponent (punkt 3) som tar seg av gjengivelsen av alle våre barn. Her er malen til en navbar-komponent:
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<!-- nav content here -->
</nav>
<router-outlet></router-outlet>
Denne <router-outlet> vil håndtere alle underordnet ruter.
Mulige problemer du kan møte og deres løsning:
- du vil kanskje sette omdirigeringen til
AppModule- bare endre stien i punkt 2 til et ekte navn, for eksempelprotected. Dette vil prefikse alle dine beskyttede URL-er med denne verdien, noe du kanskje ikke ønsker. Du har 2 muligheter å velge mellom. - du kanskje vil ha mer enn bare én modul inne i det beskyttede området - bare bruk lazy routing
- du kanskje vil skjule/vise navigasjonen, sende parametere osv. - bare kombiner det med hendelsesløsningen.
Denne metoden kan virke ikke så fleksibel, men den fungerer virkelig og dekker nesten alle tilfeller du måtte trenge. Den har ikke kompleksiteten med hendelser og utnytter fullt ut Router-funksjonene. Det beste her - den er dumt enkel og veldig lett å forstå og vedlikeholde.
