【问题标题】:How can create a dynamic menu in angular 2?如何在 Angular 2 中创建动态菜单?
【发布时间】:2016-11-15 21:50:55
【问题描述】:

在用户成功登录并使用 Angular 2 重定向到主页后,我需要创建一个动态菜单。与第一个类似问题完全相同,只是我无法对菜单项进行硬核。

Angular2: Using routes, how to display the navigation bar after successfully logged in?

#app.component.html#

<navbar>
    <!--Here I want to create menu items-->
</navbar>

<div class="container">
    <div class="col-sm-12">
        <router-outlet></router-outlet>
    </div>
</div>
<div id="footer" class="inner-wrap">
    <div class="row no-padding">
        <div class="col-sm-12 no-padding">

        </div>
    </div>
</div>

**home.component.ts**

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

 import { User } from '../_models/index';
 import { UserService } from '../_services/index';

@Component({
//moduleId: module.id,
templateUrl: 'home.component.html'
 })

export class HomeComponent implements OnInit {
users: User[] = [];

constructor(private userService: UserService) { }

 ngOnInit() {
  <!-- how we can create it here or any better place -->
    // get users from secure api end point
    this.userService.getUsers()
        .subscribe(users => {
            this.users = users;
        });
   }

}

显然我是这项技术的新手。请问有人接吗?

块引用

【问题讨论】:

  • @Downvoter,想解释一下反对意见吗?

标签: angular angular2-template angular2-services


【解决方案1】:

我设法在用户登录后立即根据用户访问权限创建动态菜单。我认为我无法在我原来的问题中正确表达要求。昨天,在搜索“如何使 2 个组件相互通信”时,我在 Angular 网站上找到了这个(见下面的链接):

https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html

我们可以通过使用 Global EventEmitter 来实现这一点。以下是我在代码中实现它的方式:

全球事件管理器:

import { Injectable, EventEmitter } from "@angular/core";

@Injectable()
export class GlobalEventsManager {
    public showNavBar: EventEmitter<any> = new EventEmitter();
    public hideNavBar: EventEmitter<any> = new EventEmitter();
}

以下链接将帮助您了解如何实现 auth guard(限制用户在未登录的情况下进入)。

http://jasonwatmore.com/post/2016/08/16/angular-2-jwt-authentication-example-tutorial

Auth.Guard.ts:

import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { GlobalEventsManager } from "../_common/gobal-events-manager";

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(private router: Router, private globalEventsManager: GlobalEventsManager) { }

    canActivate() {

        if (localStorage.getItem('currentUser')) {

            this.globalEventsManager.showNavBar.emit(true);
            return true;
        }
        else {
            // not logged in so redirect to login page
            this.router.navigate(['/login']);
            this.globalEventsManager.hideNavBar.emit(true);
            return;
        }


    }
}

menu.component.ts 中使用的模型

特点:

export class Features {
    Description: string;
    RoutePath: string;
}

menu.component.ts:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Features } from '../_models/features';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { GlobalEventsManager } from "../_common/gobal-events-manager";

@Component({
    selector: 'nav',
    templateUrl: './menu.component.html'
})

export class MenuComponent {

    showNavBar: boolean = false;
    featureList: Features[] = [];
    private headers = new Headers({ 'Content-Type': 'application/json' });

    constructor(private http: Http, private router: Router, private globalEventsManager: GlobalEventsManager) {

        this.globalEventsManager.showNavBar.subscribe((mode: any) => {
            this.showNavBar = mode;

            if (this.showNavBar = true) {
    <!-- the below function expects user id, here I have given as 1 -->
                this.getFeatureListByLoggedInUser(1)
                    .then(list => { this.featureList = list; });
            }
        });

        this.globalEventsManager.hideNavBar.subscribe((mode: any) => {
            this.showNavBar = false;
            this.featureList = [];
        });
    }

    private getFeatureListByLoggedInUser(userID: number): Promise<Features[]> {
        return this.http.get(your api url + '/Feature/GetFeatureListByUserID?userID=' + userID)
            .toPromise()
            .then(response => response.json() as Features[])
            .catch(this.handleError);
    }

    private handleError(error: any): Promise<any> {
        console.error('An error occurred', error); // for demo purposes only
        return Promise.reject(error.message || error);
    }
}

Menu.Component.html:

<div id="navbar" *ngIf="showNavBar" class="navbar-collapse collapse navbar-collapse-custom">
    <ul class="nav navbar-nav nav_menu full-width">
        <li *ngFor="let feature of featureList" class="nav_menu" routerLinkActive="active"><a class="nav-item nav-link" [routerLink]="[feature.routepath]" routerLinkActive="active">{{feature.description}}</a></li>
    </ul>
</div>

App.Component.ts:

    <!-- menu container -->
    <nav>
    </nav>
    <!-- main app container -->
    <div class="container-fluid body-content-custom">
        <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 no-padding">
            <router-outlet></router-outlet>
        </div>
    </div>

    <footer class="footer">
        &nbsp;
    </footer>


In the last, we need to register the providers of menu and global event manager in app.module.ts

app.module.ts

/// <reference path="reset-password/reset-password.component.ts" />
/// <reference path="reset-password/reset-password.component.ts" />
import './rxjs-extensions';
import { NgModule, ErrorHandler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule, XHRBackend } from '@angular/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { AuthGuard } from './_guards/auth.guard';

import { ContentHeaders } from './_common/headers';
import { GlobalEventsManager } from "./_common/gobal-events-manager";
import { MenuComponent } from "./menu/menu.component";

@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        AppRoutingModule,
        ReactiveFormsModule
    ],
    declarations: [
        AppComponent,
        MenuComponent
    ],
    providers: [
        AuthGuard,
        ContentHeaders,
        GlobalEventsManager
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

我希望这会有所帮助!

【讨论】:

    【解决方案2】:

    这就是我所做的。基本上,流程在应用程序组件中设置了一个监听器,该监听器订阅了 getLoggedIn 的 observable。当该 observable 发出(用户登录)时,我调用 app.menu.service 登录菜单。注销时,反之亦然,我得到 noLoginMenu。

    app.menu.service:

    import {RouterModule, RouterLinkActive, RouterLink} from '@angular/router';
    import {Injectable} from '@angular/core';
    import { Observable  } from 'rxjs/Observable';
    import { Subject } from 'rxjs/Subject';
    import { Subscription } from 'rxjs';
    
    
    @Injectable()
    export class AppMenuService {
    
      constructor() {
    
      }
    
      getNoLoginMenu() {
        return [
          {
            label: 'Home',
            routerLink: ['']
          },  {
            label: 'Documents',
            routerLink: ['/document']
          }, {
            label: 'Calculator',
            routerLink: ['/calculator']
          }, {
            label: 'Verify',
            routerLink: ['/verify']
          }, {
            label: 'About',
            routerLink: ['/about']
          }];
      }
    
      getLoggedInMenu() {
        return [
          {
            label: 'Home',
            routerLink: ['']
          }, {
            label: 'Documents',
            routerLink: ['/document']
          }, {
            label: 'Food',
            routerLink: ['/food']
          }, {
            label: 'Calculator',
            routerLink: ['/calculator']
          }, {
            label: 'Settings',
            routerLink: ['/settings']
          }, {
            label: 'Themes',
            routerLink: ['/themes']
          }, {
            label: 'About',
            routerLink: ['/about']
          }, {
            label: 'Logout',
            routerLink: ['/logout']
            //command: (event: Event) => { this.onLogout() }
          }];
      }
    }
    

    app.component.ts

    export class AppComponent implements OnInit, OnDestroy {
        private items: MenuItem[];
        appPageHeaderDivStyle: {};
        selectedTheme: Theme;
        errorMessage: string;
        loggedIn: LoggedIn;
        loggedInEmail: string = "";
        isLoggedIn: boolean;
        themeSub: Subscription;
        loggedInSub: Subscription;
        profileSub: Subscription;
    
        constructor(
            private as: AppMenuService,
            private ts: ThemeService,
            private ss: SettingsService,
            private fs: FoodService,
            private ls: LoginService) {
        }
    
        @HostListener('window:beforeunload', ['$event'])
        beforeUnloadHander(event) {
            var shutdown = this.onShutdown();
            //event.preventDefault();
    
        }
    
        ngOnInit() {
    
            this.themeSub = this.ts.getNewTheme()
                .subscribe(
                theme => this.selectedTheme = theme,
                error => {
                    this.errorMessage = error
                },
                () => this.completeGetNewTheme()
                );
    
            this.ts.setTheme("Pepper-Grinder");
            this.items = this.as.getNoLoginMenu();
    
            this.ls.getLoggedIn()
                .subscribe(
                loggedIn => {
                    if (loggedIn.error != undefined && loggedIn.error === "" && loggedIn.email != "") {
                        this.items = this.as.getLoggedInMenu();
    
                        var us = this.ss.getUserSettings();
                        if (us != undefined && us.theme != null && us.theme != "") {
                            this.ts.setTheme(us.theme);
                        }
    
    
                    }
                    else {
                        this.items = this.as.getNoLoginMenu();
                        this.ts.setTheme("Pepper-Grinder");
                    }
    
                    this.completeLoggedIn(loggedIn.email);
                });
        }
    
    
        ngOnDestroy() {
            if (this.themeSub) {
                this.themeSub.unsubscribe();
            }
    
            if(this.loggedInSub) {
                this.loggedInSub.unsubscribe();
            }
    
            if(this.profileSub) {
                this.profileSub.unsubscribe();
            }
        }
    
    
        completeLoggedIn(email: string) {
            this.loggedInEmail = email;
            this.isLoggedIn = (this.loggedInEmail.length > 0);
        }
    
        completeGetNewTheme() {
            this.appPageHeaderDivStyle = this.ts.getAppPageHeaderDivStyle();
        }
    
        onShutdown(): boolean {
            var ok = true;
            this.fs.completeUpdateDailyFood();
            this.profileSub = this.ss.updateProfileInformation(this.ss.getUserSettings())
                .subscribe(
                status => {
                    console.log("logout - updated user");
                },
                error => {
                    ok = false;
                },
            );
            return ok;
        }
    
        onLogout() {
        }
    }
    

    登录服务:

     loginUser(localUser: LocalUser) {
            this.authSub = this.auth.loginUser(localUser)
                .subscribe(
                token => {
                    this.token = token
                },
                error => {
                    this.isLoggingIn = false;
                    var errorObject = JSON.parse(error._body);
                    this.errorMessage = errorObject.error_description;
                    console.log(this.errorMessage);
                    this.setLoggedIn({ email: "", password: "", error: this.errorMessage });
    
                },
                () => this.completeLogin(localUser));
        }
    

    【讨论】:

    • 您好约翰,感谢您的早日回复。但这并不能解决我的问题。实际上我想根据用户的权限创建一个动态菜单,角度为 2?导航栏在 app.component.html 中,但我需要通过 home.component.ts 文件创建。我希望它现在对你有意义。
    【解决方案3】:

    我通过基于用户权限的过滤器运行菜单项数组来做到这一点。 Array.prototype.filter()

    【讨论】:

      猜你喜欢
      • 2016-12-25
      • 2017-03-13
      • 2021-02-14
      • 1970-01-01
      • 1970-01-01
      • 2020-05-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-12
      相关资源
      最近更新 更多