Angular 2基于路线隐藏某些页面上的导航

时间:2016-10-24 08:58:31

标签: angular angular2-services angular2-guards

我试图在用户查看某些页面时自动隐藏导航。例如,如果用户正在查看登录页面,则不应显示该菜单。

到目前为止我所尝试的是我有一个Navigator服务,它将改变一个" show navigation"标记基于当前页面的URL路径。这可以通过App Guard访问,其目前的工作是将下一个URL传递给Navigator服务并更新" show navigation"标志。

测试我通过点击事件更新视图以检查服务是否正在接收正确的数据并进行相应的更新。

我唯一的问题是我无法想出一种订阅/收听"显示导航"的变化的方法。旗帜"所有的时间"。我的意思是我希望导航被隐藏并自动显示。

导航器服务

import { Injectable } from '@angular/core';

import { Observable } from 'rxjs/Observable';

@Injectable()
export class NavigatorService {
    private showNavigation: boolean = false;

    displayNavigation(): Observable<boolean> {
        return Observable.of(this.showNavigation);
    }

    toggleNavigation(urlPath: string) {
        if (urlPath === 'login') {
            this.showNavigation = false;
        } else {
            this.showNavigation = true;
        }
    }
}

App Guard

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate } from '@angular/router';

import { Observable } from 'rxjs/Observable';

import { NavigatorService } from '../services';

@Injectable()
export class AppGuard implements CanActivate {
    constructor(private navigatorService: NavigatorService) { }

    canActivate(next: ActivatedRouteSnapshot) {
        console.log(next);

        this.navigatorService.toggleNavigation(next.url[0].path);

        // for now returning Observable of true...
        // will be changed when extra functionality is added
        return Observable.of(true);
    }
}

应用组件

import { Component } from '@angular/core';

import { NavigatorService } from './shared';


@Component({
    selector: 'app',
    styleUrls: [
        './app.style.css'
    ],
    template: require('./app.component.html')
})
export class AppComponent {
    showNavigation: boolean = true;

    constructor(private navigatorService: NavigatorService) { }

    // button click event
    toggleNav() {
        this.navigatorService.displayNavigation
            .subscribe(res => this.showNavigation = res);
    }
}

应用组件模板

<button (click)="toggleNav()">Toggle Navigation</button>
<div id="page-wrapper">
    <div id="sidebar-wrapper" *ngIf="showNavigation">
        <navigation></navigation>
    </div>
    <div id="page-content-wrapper">
        <main>
            <router-outlet></router-outlet>
        </main>
    </div>
</div>

从上面作为测试可以看出,我有一个&#34;切换导航&#34;按钮,以便我可以订阅该服务。说实话,我不知道这是不是最好的实现,也许我没有以正确的方式去做。我想询问是否有某种方式可以让应用程序组件始终了解&#34;显示导航&#34;旗帜的价值。

更新 - 问题已解决

我已经按照这个question正确引导我回答了问题。我更新了导航服务,如下所示:

导航器服务

import { Injectable } from '@angular/core';

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class NavigatorService {
    private showNavigation: Subject<boolean>;

    constructor() {
        this.showNavigation = <Subject<boolean>>new Subject();
    }

    get displayNavigation(): Observable<boolean> {
        return this.showNavigation.asObservable();
    }

    toggleNavigation(urlPath: string) {
        let showNav: boolean;
        if (urlPath === 'login') {
            showNav = false;
        } else {
            showNav = true;
        }

        this.showNavigation.next(showNav);
    }
}

然后我在App Component ngOnInit生命周期钩子中订阅了该服务:

import { Component, OnInit } from '@angular/core';

import { NavigatorService } from './shared';

@Component({
    selector: 'app',
    styleUrls: [
        './app.style.css'
    ],
    template: require('./app.component.html')
})
export class AppComponent implements OnInit {
    showNavigation: boolean = true;

    constructor(private navigatorService: NavigatorService) { }

    ngOnInit() {
        this.navigatorService.displayNavigation
            .subscribe(res => this.showNavigation = res);
    }
}

我仍然不能100%确定这是否是最佳方法,但到目前为止我已解决了我的问题。

1 个答案:

答案 0 :(得分:0)

对于其他人&#39;参考,你可以只使用路由器。我在下面有一个示例,其中我在AppComponent的模板中只有<router-outlet></router-outlet>,并将您想要隐藏的所有内容移动到名为DefaultLayoutComponent的单独布局视图中。

将您的菜单/页脚和<router-outlet></router-outlet>放在DefaultLayoutComponent中。现在,只有DefaultLayoutComponent的子项(即下面的仪表板和邀请组件)才具有公共布局。其他页面(即下面的登录)将采用空白布局。

RouterModule.forRoot([
  { path: 'login', component: LoginComponent},
    { path: '', component: DefaultLayoutComponent, children: [
      { path: '', component: DashboardComponent},
      { path: 'dashboard', component: DashboardComponent },
      { path: 'invite', component: InviteComponent}]
    },
  { path: '**', redirectTo: ''}
])