2016-11-23 117 views
3

对于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

+0

你的AppComponent有2个,它们都没有'name =“xxx”'。每个路由只能有一个未命名的路由器出口。 –

+0

@GünterZöchbauer尽管'* ngIf'只有1个可见?我在控制台中没有错误。 –

+0

啊,对不起,我错过了第一个'* ngIf'。 –

回答

3

从@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> 

我会接受这样的答案,但由于上述的用户来帮我在我的道路上。

2

我相信这个问题是双路由器出口的上述意见建议。我在我的项目中做了这样的事情。

这是我的解决方案:

我首先创建一个服务,以确定登录的状态(我认识到,事件发射器是不是,我工作的这个改变对行为主体的良好做法):

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> 
+0

如果你把'router-outlet's放在div里(这样总共有两个),这对你有用吗?我尝试过,但我认为问题是由'* ngIf'引起的,摘要已经完成,然后'router-outlet'被添加到DOM。或类似的东西这就是我现在想的至少 –

+0

你应该只有一个路由器插座。我认为这就是你刚才建议的问题 – Bhetzie

0

将您的导航电话置于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']); 
}); 
相关问题