Angular 2 - 内容无法在路由器插座中加载
对于Angular 2,我仍然很新,希望你们能帮助我。Angular 2 - 内容无法在路由器插座中加载
我有一个相当简单的应用程序,有一个登录页面,成功登录后,用户被定向到一个带有sidemenu的页面。登录屏幕没有这个侧边菜单。当用户注销时,他将被重定向到登录页面。
问题是,登录后sidemenu变得可见,但其他内容仅在刷新后才可见。只有在刷新内容(登录页面)后,注销后页面才为空,注销时也是如此。我可能做错了什么,但即使看了其他问题,我也弄不清楚。
这里是我的路由:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProfileComponent } from './profile-component/profile-component.component'
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { LoginComponent } from './login/login.component';
import { LoggedInGuard } from './logged-in/logged-in.guard';
const appRoutes: Routes = [
{path: 'profile', component: ProfileComponent, canActivate: [LoggedInGuard]},
{path: 'login', component: LoginComponent},
{path: '', component: LoginComponent},
{path: '**', component: PageNotFoundComponent},
];
@NgModule({
imports: [
RouterModule.forRoot(appRoutes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {
}
的LoginComponent
:
import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {LoginService} from '../login-service/login-service.service';
import {Router} from '@angular/router';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
providers: [ LoginService ]
})
export class LoginComponent implements OnInit {
loginForm: FormGroup;
error: String;
constructor(private formBuilder: FormBuilder,
private loginService: LoginService,
private router: Router) {
}
ngOnInit() {
if (this.loginService.isLoggedIn()) {
this.router.navigate(['/profile']);
}
this.loginForm = this.formBuilder.group({
username: ['', Validators.required],
password: ['', Validators.required]
});
}
login(): void {
let self = this;
this.loginService.login(this.loginForm.value.username, this.loginForm.value.password).subscribe(function (result) {
if (result) {
self.router.navigate(['/profile']);
}
}, function (error) {
self.error = 'Invalid';
});
}
}
的AppComponent
HTML看起来像这样:
<md-toolbar color="primary" *ngIf="isLoggedIn()">
<span>Sporter volgsysteem</span>
</md-toolbar>
<md-sidenav-layout *ngIf="isLoggedIn()">
<md-sidenav #start mode="side" [opened]="true">
<a routerLink="/add" routerLinkActive="active" md-button color="primary" disabled="false"><md-icon class="icon">add</md-icon><span class="nav-item">Toevoegen</span></a>
<a routerLink="/compare" routerLinkActive="active" md-button color="primary"><md-icon class="icon">swap_horiz</md-icon><span class="nav-item">Vergelijken</span></a>
<a routerLink="/search" routerLinkActive="active" md-button color="primary"><md-icon class="icon">search</md-icon><span class="nav-item">Zoeken</span></a>
<a routerLink="/profile" routerLinkActive="active" md-button color="primary"><md-icon class="icon">account_box</md-icon><span class="nav-item">Profiel</span></a>
<a routerLink="/feedback" routerLinkActive="active" md-button color="primary"><md-icon class="icon">feedback</md-icon><span class="nav-item">Feedback</span></a>
<a routerLink="/faq" routerLinkActive="active" md-button color="primary"><md-icon class="icon">info</md-icon><span class="nav-item">FAQ</span></a>
<div class="spacer"></div>
<a md-button color="primary" routerLink="/login" (click)="logout()"><md-icon class="icon">exit_to_app</md-icon><span class="nav-item">Uitloggen</span></a>
</md-sidenav>
<router-outlet></router-outlet>
</md-sidenav-layout>
<router-outlet *ngIf="!isLoggedIn()"></router-outlet>
AppComponent
:
import {Component} from '@angular/core';
import {LoginService} from "./login-service/login-service.service";
import {Router } from '@angular/router'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
providers: []
})
export class AppComponent {
constructor(private loginService : LoginService,
private router: Router) {
}
logout() {
this.loginService.logout();
this.router.navigate(['/login']);
}
isLoggedIn() {
return this.loginService.isLoggedIn();
}
}
那么为什么登录后不显示ProfileComponent
的内容,为什么登出后登录页面不显示,但是刷新时都显示?
更新
大多数建议,这是由于多个无名router-outlet
其实如此,以验证我删除一个出口,并显示sidemenu布局所有的时间。当然为了测试目的。这并没有解决问题,它给了我相同的行为:配置文件内容只在刷新后加载。
更新2 我猜这是关系到使用*ngIf
显示router-outlet
从@bhetzie和@海梅·托雷斯按照上面的意见和我自己的假设,我进一步调查。 事实证明,问题确实与双重router-outlet
。
我的解决方案是提取一个LoginModule
模块,然后在该模块中重定向到登录页面。在所有其他情况下,我转到另一个名为SvsModule
的模块,该模块显示带有侧面导航结构的登录内容。
所以SvsModule
有下列路由:
RouterModule.forChild([
{path: 'svs', component: ProfileComponent, canActivate:[LoggedInGuard]},
{path: 'svs/profile', component: ProfileComponent, canActivate:[LoggedInGuard]}
])
而且ProfileComponent使用以下HTML:
<md-sidenav-layout>
<md-sidenav #start mode="side" [opened]="true">
<md-nav-list>
<a routerLink="/add" routerLinkActive="active" md-button color="primary" disabled="false">
<md-icon class="icon">add</md-icon>
<span class="nav-item">Toevoegen</span>
</a>
<a routerLink="/compare" routerLinkActive="active" md-button color="primary">
<md-icon class="icon">swap_horiz</md-icon>
<span class="nav-item">Vergelijken</span>
</a>
<a routerLink="/search" routerLinkActive="active" md-button color="primary">
<md-icon class="icon">search</md-icon>
<span class="nav-item">Zoeken</span>
</a>
<a routerLink="/profile" routerLinkActive="active" md-button color="primary">
<md-icon class="icon">account_box</md-icon>
<span class="nav-item">Profiel</span>
</a>
<a routerLink="/feedback" routerLinkActive="active" md-button color="primary">
<md-icon class="icon">feedback</md-icon>
<span class="nav-item">Feedback</span>
</a>
<a routerLink="/faq" routerLinkActive="active" md-button color="primary">
<md-icon class="icon">info</md-icon>
<span class="nav-item">FAQ</span>
</a>
<div class="spacer"></div>
<a md-button color="primary" routerLink="/login" (click)="logout()">
<md-icon class="icon">exit_to_app</md-icon>
<span class="nav-item">Uitloggen</span></a>
</md-nav-list>
</md-sidenav>
<router-outlet></router-outlet>
</md-sidenav-layout>
我会接受这样的答案,但由于上述的用户来帮我在我的道路上。
我相信这个问题是双路由器出口的上述意见建议。我在我的项目中做了这样的事情。
这是我的解决方案:
我首先创建一个服务,以确定登录的状态(我认识到,事件发射器是不是,我工作的这个改变对行为主体的良好做法):
GlobalEventsManager
import { EventEmitter, Injectable } from '@angular/core';
@Injectable()
export class GlobalEventsManager {
public showNavBar: EventEmitter<boolean> = new EventEmitter<boolean>();
}
我用我的路线来检查,如果登录令牌未过期的authguard。我用angular2,智威汤逊库这个
AuthGuard
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { tokenNotExpired } from 'angular2-jwt';
import { GlobalEventsManager } from './GlobalEventsManager';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private globaleventsManager: GlobalEventsManager) {}
canActivate(next: ActivatedRouteSnapshot,
state: RouterStateSnapshot) {
if (tokenNotExpired('currentUser')) {
this.globaleventsManager.showNavBar.emit(true);
return true;
} else {
localStorage.removeItem('currentUser');
this.router.navigate(['/login']);
return false;
}
}
}
当使用我的登录组件在用户登录,我设置了GlobalEventsManager为true
登录
constructor(
private router: Router,
private authenticationService: AuthenticationService,
private globaleventsManager: GlobalEventsManager) { }
ngOnInit() {
// reset login status
this.authenticationService.logout();
this.globaleventsManager.showNavBar.emit(false);
}
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe((result) => {
this.globaleventsManager.showNavBar.emit(true);
this.router.navigate(['/']);
在我的导航栏中,我订阅了GlobalEventsManager并设置了一个布尔属性的结果:
导航栏
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { NavActiveService } from '../../../services/navactive.service';
import { GlobalEventsManager } from '../../../services/GlobalEventsManager';
@Component({
moduleId: module.id,
selector: 'my-navbar',
templateUrl: 'navbar.component.html',
styleUrls:['navbar.component.css'],
})
export class NavComponent {
showNavBar: boolean = true;
constructor(private router: Router,
private globalEventsManager: GlobalEventsManager){
this.globalEventsManager.showNavBar.subscribe((mode:boolean)=>{
this.showNavBar = mode;
});
}
}
在我的导航栏HTML我现在可以创建两个导航栏,一个导航栏只是有一个登录导航,当我authguard通知,一个toekn已过期或用户没有登录,只显示导航栏作为选项登录。一旦登录,GlobalEventsManager值的变化,我的记录在导航栏显示:
导航栏HTML
<div *ngIf="showNavBar">
//My logged in navbar
</div>
<div *ngIf="!showNavBar">
//navbar that just displays login as an option
</div>
如果你把'router-outlet's放在div里(这样总共有两个),这对你有用吗?我尝试过,但我认为问题是由'* ngIf'引起的,摘要已经完成,然后'router-outlet'被添加到DOM。或类似的东西这就是我现在想的至少 –
你应该只有一个路由器插座。我认为这就是你刚才建议的问题 – Bhetzie
将您的导航电话置于ngZone。 (Angular 5)
import { NgZone } from "@angular/core";
import { Router } from "@angular/router";
constructor(
private ngZone: NgZone,
private router: Router
) {}
...
this.ngZone.run(() => {
this.router.navigate(['/profile']);
});
你的AppComponent有2个,它们都没有'name =“xxx”'。每个路由只能有一个未命名的路由器出口。 –
@GünterZöchbauer尽管'* ngIf'只有1个可见?我在控制台中没有错误。 –
啊,对不起,我错过了第一个'* ngIf'。 –