Search code examples
angularangular2-templateangular2-services

How can create a dynamic menu in angular 2?


I need to create a dynamic menu after user logged in successfully and redirected to home page using Angular 2. Exactly like in the first similar question except I cannot hardcore the menu items.

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;
        });
   }

}

Clearly I am new to this technology. Please anybody pick this up?

Blockquote


Solution

  • I managed to Create dynamic menu based on user access right after the user logs in. I think I was not able to articulate the requirement properly in my original question. Yesterday, while searching "how to make 2 components communicate with each other" I found this on the angular website (see link below):

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

    We can achieve this by using a Global EventEmitter. Here is how I implemented it in my code:

    GlobalEventManager:

    import { Injectable, EventEmitter } from "@angular/core";
    
    @Injectable()
    export class GlobalEventsManager {
        public showNavBar: EventEmitter<any> = new EventEmitter();
        public hideNavBar: EventEmitter<any> = new EventEmitter();
    }
    

    The below link will help you to understand how to implement auth guard (restricting a user to enter without login).

    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;
            }
    
    
        }
    }
    

    Model used in menu.component.ts

    Features:

    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 { }
    

    I hope this will help!