3

これは私にとっては非常に混乱しています。私はサブスクリプションの仕組みをしっかり理解していないかもしれません。角度2の購読値の変更はHTMLに反映されません

角度2最終版

目標:役割 アプローチに基づく表示/非表示のナビゲーションメニュー:私は、ユーザーを認証するためのFacebookを使用しています。認証後、ユーザーの役割が取得され、管理メニューを表示するかどうかを決定するために使用されます。 observable.next呼び出しがtrueで実行され、nav bar compenentサブスクリプションがフラグを受け取り、isAdminをtrueに変更します(isAdminはfalseで始まります)。これによりAdminメニューが表示されます。

問題:真のフラグがサブスクライバによって正しくピックアップされ、isAdminがtrueに設定されています。ただし、Adminメニューは表示されません。

navbar.component.ts

@Component({ 
selector: 'as-navbar', 
templateUrl: 'app/shared/navbar/navbar.html', 
changeDetection: ChangeDetectionStrategy.OnPush 
}) 
export class NavbarComponent { 
@Input() brand: string; 
public isAdmin:boolean; 

constructor(private _securityService:SecurityService){ 
    let self = this; 

    this._securityService.isAdminObservable.subscribe(function (flag) { 
     this.isAdmin = flag; 
     console.log('subscribe received on navbar'); 
    }.bind(this)); 
} 
} 

navbar.html

 <li class="dropdown" *ngIf="isAdmin"> 
     <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a> 
     <ul class="dropdown-menu"> 
     <li><a [routerLink]="['/campaigns']">Campaigns</a></li> 
     <li><a [routerLink]="['/products']">Products</a></li> 
     <li><a [routerLink]="['/products']">Reports</a></li> 
     </ul> 
    </li> 

app.component.ts

constructor(private _http: Http, private _jsonp: Jsonp, private _securityService:SecurityService) { 
    this.appBrand = CONSTANTS.MAIN.APP.BRAND; 

    let self = this; 
    setInterval(function(){ 
     self._securityService.setAdminStatus(true); 
     console.log('set from app component'); 
    }, 5000) 
} 

security.service.ts

​​

何か問題がありますか?または、目標を達成するためのより良いアプローチがありますか? どのようなご提案も大歓迎です! おかげpeeskilletが提供する答えを

UPDATE

は、私がコンポーネントからchangeDetectionラインを削除し、それが動作します。私はさらに、コード上で動作するとき

しかし、私は、別のサービス(この場合、Facebookのサービス)に

self._securityService.setAdminStatus(isAdmin); 

を移動させ、アプリ成分からそのサービスを呼び出します。 navbar.compoenent.tsに登録すると変更が反映されますが、変更の検出は行われません。私はそれを動作させるために検出を手動でトリガーする必要があります。

更新navbar.component.ts

@Component({ 
selector: 'as-navbar', 
templateUrl: 'app/shared/navbar/navbar.html' 
}) 
export class NavbarComponent { 
@Input() brand: string; 
public isAdmin:boolean=false; 

constructor(private _securityService:SecurityService, private cdr: ChangeDetectorRef){ 
    this._securityService.isAdminObservable.subscribe(function (flag) { 
      this.isAdmin = flag; 
      this.cdr.detectChanges(); 
      console.log('subscribe received on navbar'); 
     }.bind(this)); 
    } 
} 

更新app.component.ts

@Component({ 
    selector: 'as-main-app', 
    templateUrl: 'app/app.html' 
}) 
export class AppComponent { 
    public appBrand: string; 
    constructor(private _http: Http, 
      private _facebookService:FacebookService 
) { 
     this.appBrand = CONSTANTS.MAIN.APP.BRAND; 
     this._facebookService.GetLoginStatus(); 
    } 
} 

これはかなり面白いです。明らかに、私は角度2の変化の検出についてもっと学ぶ必要があります。誰もが良いリファレンスを知っている場合は、私と共有してください。

ありがとうございました!

答えて

1

changeDetection: ChangeDetectionStrategy.OnPushを使用しているためです。これは、@Inputの入力が変更された場合にのみ、コンポーネントの変更検出が行われることを意味します。

@Component.changeDetectionを削除しても問題ありません。

あなたの目標はにOnPush戦略を維持し、その後、1つのオプションを明示的ChangeDetectorRef

class SomeComponent { 
    message; 

    constructor(private service: Service, private cdr: ChangeDetectorRef) { 
    } 

    ngOnInit() { 
    this.service.subscribe(data => { 
     this.message = data; 
     this.cdr.detectChanges(); 
    }) 
    } 
} 

を使用して、変化検出を強制することですにある場合 - またChangeDetectionStrategy.OnPush and Observable.subscribe in Angular 2を参照してください。

+0

これは素晴らしいです!答えをありがとう。私はchangeDetectionを削除しました:ChangeDetectionStrategy.OnPushとコードが動作します! 興味深いものがあります。私はロジックを別のサービスに移しました。(Facebookサービス)Facebookがユーザー情報を返すとき、私はデータベースからロールを拾い、次にnext()フラグを使います。サブスクライバがそれを取得しましたが、変更は検出されませんでした。私はまだそれを動作させるために手動でchangeDetectionを起動する必要があります。なぜ私は不思議です。私はコードを更新しました。 – Chuck

+0

いや、わからない。 –

+0

あなたの記事の一番下にあるあなたのコメントに関しては、[ここには素晴らしい参考文献があります](http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html) –

関連する問題