2016-12-18 16 views
0

私はAngular2を初めて使用しており、サービスの属性が変更されたときに親コンポーネントと子コンポーネントのアクションパターンを決定しようとしています。 providers属性のapp.component.ts)。私が使用しています:5.0.0-beta.12 Angular2はサービス内の属性の変更を確認します

  • typescriptです2.2.1
  • は基本的にサービスがリモートAPIに接続し、このAPI

  • 2.2.1

    • 角度rxjsをトークン認証が必要です。サービスは公開login()logout()の機能を持っています。前者はAPIを呼び出し、プライベート属性tokenをトークン文字列(有効なログインの場合)または "(無効なログインの場合)に設定します。 APIを呼び出す他のすべてのパブリック関数は、このプライベートトークンを使用します。

      トークン属性を表示または使用するために、このサービスを使用するコンポーネントは、APIのビジネスプロセスに「ダム」し、これを介してのみデータを消費する必要があるため、サービス。

      サービス(簡体字)

      import { Injectable } from '@angular/core'; 
      import { Http, Response, Headers, URLSearchParams } from '@angular/http'; 
      import {Observable, Subject} from 'rxjs/Rx'; 
      import 'rxjs/add/operator/catch'; 
      import 'rxjs/add/operator/map'; 
      
      @Injectable() 
      export class ApiService { 
          private url:string = 'my.service.com/'; 
          private username: string; 
          private password: string; 
          private token: string; 
      
          constructor (private http: Http) {} 
      
          public getUsername(): string { 
          return this.username; 
          } 
      
          public setUsername(username: string) { 
          this.username = username; 
          } 
      
          public getPassword(): string { 
          return this.password; 
          } 
      
          public setPassword(password: string) { 
          this.password = password; 
          } 
      
          private setToken(token: string) { 
          this.token = token; 
          } 
      
          public login() { 
          let headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }); 
          let urlSearchParams = new URLSearchParams(); 
          urlSearchParams.append('username', this.username); 
          urlSearchParams.append('password', this.password); 
          let body = urlSearchParams.toString(); 
          let url = this.url + 'user/login'; 
          this.http.post(url, body, {headers: headers}) 
           .map(res => {this.setToken(typeof res['token'] !== 'undefined' ? res['token'] : '');}); 
          } 
      
          public logout() { 
          this.setToken(''); 
          } 
      
          public getData() { 
          let headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }); 
          let urlSearchParams = new URLSearchParams(); 
          urlSearchParams.append('token', this.token); 
          let body = urlSearchParams.toString(); 
          let url = this.url + 'data'; 
          return this.http.get(url, body, {headers: headers}) 
           .map(res => res.json()); 
          } 
      

      app.component.ts

      import { Component, ViewEncapsulation } from '@angular/core'; 
      import { ApiService } from './services/api'; 
      
      @Component({ 
          selector: 'app', 
          encapsulation: ViewEncapsulation.None, 
          styleUrls: ['./app.component.global.scss'], 
          templateUrl: './app.component.html', 
          providers: [ApiService] 
      }) 
      
      export class AppComponent { 
          constructor(private apiService: ApiService) {} 
      } 
      

      子コンポーネントにはどうすればよい

      import { Component } from '@angular/core'; 
      import { ApiService } from '../services/api'; 
      
      @Component({ 
          selector: 'child-component', 
          styleUrls: ['./child-component.component.scss'], 
          templateUrl: './child-component.component.html' 
      }) 
      
      export class ChildComponent { 
          data: any[]; 
          constructor(private apiService: ApiService) {} 
      } 
      

      私はコンポーネント(ChildComponentのようにプライベート属性tokenの状態をApiServiceに観察し、それが ''ではない場合、トークンを必要とするサービス内の関数を呼び出すようにします。 getData())?おそらく私は間違った方法でこれに近づいていますが、この方法でそれに近づく理由は、データをフェッチ/送信して表示するために有効なトークンに依存する子コンポーネントがいくつかあり、ログインに成功したときだけデータを取得/私は様々なngOnChanges、Observerable、Subject.emitなどを試してきましたが、この作業を行うことはできませんでした。

    答えて

    0

    子コンポーネントは、サービスの状態について知っている必要はありません。

    子コンポーネントがgetData()を使用する場合、サービスは有効なトークンを持っているかどうかをチェックできます。そうでないと、ログインで取得してからGETを実行できます。

    トークンが見つからない場合にユーザーがコンポーネントを読み込まないようにするには、ルートガードを使用できます。

    はたぶん、あなたは必要ありません何が、ここで警備員の良い読書:ヨハンへ http://blog.thoughtram.io/angular/2016/07/18/guards-in-angular-2.html

    +0

    感謝その返事ヨハン、それはきちんとした解決策ですが、私の要件にはあまり適合しません。私はページを常に利用可能にしたかったのですが、ユーザーがログインしているときに、ページの特定の子コンポーネントのみが表示されるようにしておく必要がありました。しかし、私はあなたの答えを役に立つものとしてアップグレードしています。 – vim

    +0

    申し訳ありませんが、これをupvoteアップすることはできません、私はrep <15があります。しかし、記録されています。 – vim

    0

    おかげで、しかし、私は、ページが利用できるようにし、ユーザーがログインしている場合にのみデータを取り込むために、いくつかの子コンポーネントを持つようにしたいですin

    解決策はDelegation: EventEmitter or Observable in Angular2です。このようにして

    、トークンが変更されるまで、私は要求を行っている子コンポーネントを防ぐことができます(つまり、ログイン()が正常に呼び出されました):用

    import { Injectable } from '@angular/core'; 
    import { Http, Response, Headers, URLSearchParams } from '@angular/http'; 
    import {Observable, Subject} from 'rxjs/Rx'; 
    import 'rxjs/add/operator/catch'; 
    import 'rxjs/add/operator/map'; 
    
    @Injectable() 
    export class ApiService { 
        private url:string = 'my.service.com/'; 
        private username: string; 
        private password: string; 
        private token: string; 
    
        constructor (private http: Http) {} 
    
        private setToken(token: string) { 
        this.tokenValue = token; 
        this.token.next(token); 
        } 
    
        public login() { 
        let headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }); 
        let urlSearchParams = new URLSearchParams(); 
        urlSearchParams.append('username', this.username); 
        urlSearchParams.append('password', this.password); 
        let body = urlSearchParams.toString(); 
        let url = this.url + 'user/login'; 
        this.http.post(url, body, {headers: headers}) 
         .map(res => {this.setToken(typeof res['token'] !== 'undefined' ? res['token'] : '');}); 
        } 
    
        public logout() { 
        this.setToken(''); 
        } 
    
        public getData() { 
        let headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' }); 
        let urlSearchParams = new URLSearchParams(); 
        urlSearchParams.append('token', this.token); 
        let body = urlSearchParams.toString(); 
        let url = this.url + 'data'; 
        return this.http.get(url, body, {headers: headers}) 
        .map(res => res.json()); 
        } 
    

    子コンポーネント

    import { Component } from '@angular/core'; 
    import { ApiService } from '../services/api'; 
    import { Subscription } from 'rxjs/Rx'; 
    
    @Component({ 
        selector: 'child-component', 
        styleUrls: ['./child-component.component.scss'], 
        templateUrl: './child-component.component.html' 
    }) 
    
    export class ChildComponent { 
        tokenSubscription: Subscription; 
        data: any[]; 
        constructor(private apiService: ApiService) {} 
    
    ngOnInit() { 
        this.tokenSubscription = this.apiService.changeToken$ 
        .subscribe(token => { this.apiService.getData().subscribe(res => this.data = res.json())); 
    } 
    
    ngOnDestroy() { 
        this.tokenSubscription.unsubscribe(); 
        } 
    } 
    
    関連する問題