首页 文章

Angular 2:在身份验证时在导航栏中显示图标

提问于
浏览
0

我的组件结构看起来大致如此 . 我的应用程序组件有一个导航栏和路由器插座 . 导航栏包含徽标,一些通用链接以及一些仅在用户登录和身份验证时显示的特定链接 . 路由器插座根据路由URL加载主组件或墙组件 . 主组件包含登录组件,其中包含常规用户标识,密码和提交按钮 . 在提交时,登录成功后,登录组件将发出一个事件 . 现在,我如何在home组件(父组件)中捕获该事件?

如果我直接在应用程序下使用主页选择器,我可以捕获该事件,将其冒泡到应用程序,然后使导航栏中的隐藏链接可见 .

我不知道如何捕获home组件中登录组件发出的事件,因为它已加载到路由器输出中 .

<!-- app.html -->
<div>
  <nav>
    <!-- Product logo -->
    <!-- Some generic links -->
    <!-- some hidden icons to be shown on authentication -->
  </nav>
  <router-outlet></router-outlet>
</div>

<!-- home.html -->
<div>
  <login></login>
</div>

<!-- login.html -->
<div>
  <!-- user name and password -->
  <!-- submit button - the associated ts file raises an event on successful login -->
</div>

<!-- wall.html -->
<div>
  <!-- Content to be displayed on authentication -->
</div>

谢谢,希尔帕

3 回答

  • 0

    我想出了这个问题,虽然我还没有解决方案 . 原来在 Map 上调用的方法无法访问类级对象 . 如果我通过身份验证调用发出事件,它就可以正常工作 . 我尝试将事件 Launcher 对象传递给映射方法,但这也没有帮助 . 如何将对象传递给映射方法范围?

    我服务中的代码如下所示:

    authenticate(authRequest: login): Observable<user> {
            let url: string = this.apiUrl + AppSettings.LOGIN_SERVICE;
            let headers = new Headers({
                'Content-Type': AppSettings.CONTENT_TYPE_HEADER
            });
    
            let options = new RequestOptions({ headers: headers });
    
            return this._http.post(url, authRequest, options) // ...using post request
                .map(this.authenticated)
                .catch(this.handleError);
    
            //.catch(this.handleError);
        }
    
        private authenticated(res: Response) {
            let body = res.json();
            if (body.StatusCode === 200) {
                localStorage.setItem('auth_token', res.headers.get("access-token"));
              //This is the event declared at the class level.
              //The following line of code is the one giving the error - cannot execute emit on  undefined
                this.authEvent.emit(true);
                return body.Data || {};
            }
            else {
                return {};
            }
        }
    
  • 0

    抱歉延迟,我就是这样做的:

    auth.service.ts

    export class AuthService {
    
        authChanged: EventEmitter<any> = new EventEmitter();
    
        postLogin(f: ILoginForm) {
          return this.http.post('/login', f)
          .map(res => res.json())
          .subscribe(data => this._checkLoginResponse(data));
        }
    
        /**
         * Check Login Result
         * @param data
         */
        private _checkLoginResponse(data: any) {
          // If Successful Login
          if (data.data && data.meta && data.meta.token) {
    
            // Set User & Token
            localStorage.setItem('inctoken', data.meta.token);
            localStorage.setItem('incuser', JSON.stringify(data.data));
    
            // Emit Auth & User Events
            this.authChanged.emit(this.getUser());
    
            // Show OK Login Flash Message
            this.flash.success('You have been logged in successfully.');
    
            // Navigate Home
            this.injector.get(Router).navigate(['/']);
          }
        }
    
        /**
         * Logout of Interface
         * @returns boolean
         */
        logout(withMsg = false): boolean {
          // # Remove Token & User from LS
          localStorage.removeItem('inctoken');
          localStorage.removeItem('incuser');
    
          // Emit Auth Events
          this.authChanged.emit(false);
    
          // Show Flash Message
          if (withMsg)
            this.flash.info('You have been logged out.', 'OK.');
    
          // Redirect to Login Page
          this.injector.get(Router).navigate(['/login']);
          return true;
        }
    }
    

    然后任何组件都可以注入 AuthService 并知道authedUser何时更改,注销等 . 以我的Navbar为例:

    navbar.component.ts

    export class NavbarComponent {
    
      /**
       * Authed User
       */
      authedUser: IUser;
    
    
      constructor(private authService: AuthService) {
        this.authService.authChanged
          .subscribe((user?: IUser) => {
            // user will be false if logged out
            // or user object if logged in. 
            this.authedUser = user;
          });
        }
    }
    

    然后在我的导航栏模板中,我可以选择根据身份验证状态显示内容:

    <nav class="navbar">
    
      <!-- Truncated -->
      <ul class="menu-item"
          *ngIf="authedUser">
          <li><img [src]="authedUser.avatar"></li>
          <!-- Whatever -->
      </ul>
    
      <ul class="menu-item"
          *ngIf="!authedUser">
          <li><a [routerLink]="['/login']">Login</a></li>
          <!-- Whatever -->
      </ul>
    
    </nav>
    

    Obviously a lot of these classes are truncated for brevity.

    如果您对如何在标头中发送令牌感到好奇,这里是我创建的HttpClient类的一个简单示例(为简洁而截断):

    http.service.ts

    export class HttpClient {
    
      constructor(private http: Http) {
        // ...
      }
    
      /**
       * Get
       * @param url
       * @returns {Observable<any>}
       */
      get(url): Observable<any> {
    
        // Create New Headers
        let headers = new Headers();
    
        // Set Authorization Header
        this._createAuthorizationHeader(headers);
    
        // Create Observable to Return to Calling Service.
        // We Dont Just Return the HTTP Observable Because
        // We Need to Subscribe Here to Catch The Errors That
        // May Be Thrown, Otherwise, Every Service Would Need
        // To Call The Handle Errors Method
        return Observable.create((observer) => {
    
          // Fire Http GET Request, Subscribe & Catch Errors
          return this.http.get(this.baseUrl + url, {
            headers: headers
          }).subscribe(
            data => observer.next(data),    // Emit Data Returned
            err => this.handleError(err),   // Catch Errors
            () => observer.complete()       // Emit Completed
          );
        });
      }
    
      /**
       * Create Authorization Header
       * @param {Headers} headers
       */
      private _createAuthorizationHeader(headers: Headers) {
    
        // If We Have A Token, Append It.  The
        // API Server Will Determine Its Validity
        if (localStorage.getItem('inctoken')) {
          headers.append('Authorization', 'Bearer: ' + localStorage.getItem('inctoken'));
        }
      }
    }
    

    然后在我的其他组件中,我可以注入我的HttpClient类并使用它将令牌自动放置在 Headers 中,I.E .

    some.component.ts

    export class SomeComponent {
    
      constructor(private http: HttpClient) {
        // ...
      }
    
      private _getSomeData() {
        return this.get('/someurl')
          .map(res => res.json();
      }
    }
    
  • 0

    对这个解决方案的影响 - > http://plnkr.co/edit/KfcdDi?p=info

    //alert.service.ts
    
    import { Injectable } from '@angular/core';
    import { Router, NavigationStart } from '@angular/router';
    import { Observable } from 'rxjs';
    import { Subject } from 'rxjs/Subject';
    
    @Injectable()
    export class AlertService {
        private subject = new Subject<any>();
        private keepAfterNavigationChange = false;
    
        constructor(private router: Router) {
            // clear alert message on route change
            router.events.subscribe(event => {
                if (event instanceof NavigationStart) {
                    if (this.keepAfterNavigationChange) {
                        // only keep for a single location change
                        this.keepAfterNavigationChange = false;
                    } else {
                        // clear alert
                        this.subject.next();
                    }
                }
            });
        }
    
        success(message: string, keepAfterNavigationChange = false) {
            this.keepAfterNavigationChange = keepAfterNavigationChange;
            this.subject.next({ type: 'success', text: message });
        }
    
        error(message: string, keepAfterNavigationChange = false) {
            this.keepAfterNavigationChange = keepAfterNavigationChange;
            this.subject.next({ type: 'error', text: message });
        }
    
        getMessage(): Observable<any> {
            return this.subject.asObservable();
        }
    }
    
    //login.component
    
    private loggedIn(user1: user) {
            this.currentUser = user1;
            this._alertService.alert("login", true);
         
        }
    
    //app.component
    
    ngOnInit(): void {
            this.authenticated = this._authService.isLoggedIn();
            this._alertService.getMessage().subscribe(data => this.setData(data));
        }
    
    private setData(data: any) {
            if (!this.authenticated) {
                if (data && (data.type === 'login') && data.success === true) {
                    this.authenticated = true;
                }
                else {
                    this.authenticated = false;
                }
            }
        }
    
    <!-- app.html -->
        <nav class="navbar navbar-color">
            <div class="container-fluid" id="nav_center">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed nav-expand-button" 
                            data-toggle="collapse" data-target="#navbar-collapse1" aria-expanded="false"
                            *ngIf="authenticated">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <button type="button" class="nav-features nav-expand-button"
                            (click)="isCollapsed = !isCollapsed" *ngIf="authenticated">
                        <span class="sr-only">Navigate features</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="#">Outili</a>
                </div>
                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse" id="navbar-collapse1" *ngIf="authenticated">
                    <!--*ngIf="showNotification">-->
                    <ul class="nav navbar-nav navbar-right">
                        <li class="navbar-icons">
                            <a href="#" class="navbar-a">
                                <span class="glyphicon glyphicon-inbox navbar-icons"></span>
                            </a>
                        </li>
                        <li class="dropdown navbar-icons">
                            <a href="#" class="dropdown-toggle navbar-a" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
                                <span class="glyphicon glyphicon-user navbar-icons"></span>
                                <span class="caret navbar-icons"></span>
                            </a>
                            <ul class="dropdown-menu">
                                <li><a href="#">Profile</a></li>
                                <li><a href="#">Settings</a></li>
                                <li role="separator" class="divider"></li>
                                <li (click)="logout()"><button type="button" class="btn">Logout</button></li>
                            </ul>
                        </li>
                    </ul>
                </div><!-- /.navbar-collapse -->
            </div><!-- /.container-fluid -->
        </nav>
    

    这里的提醒服务完全符合我的要求 .

相关问题