7

これは私をかなり混乱させます。サブスクリプションのしくみをしっかりと理解していない可能性があります。

Angular 2 の最終版

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

問題: true フラグがサブスクライバーによって適切に取得され、isAdmin が true に設定されます。ただし、管理者メニューは表示されません。

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

@Injectable()
export class SecurityService{
public isAdmin:Subject<boolean>=new Subject<boolean>();
public isAdminObservable = this.isAdmin.asObservable();

constructor(){}

setAdminStatus(flag){
    this.isAdmin.next(flag);
    }
}

これに何か問題がありますか?または、目標を達成するためのより良いアプローチがありますか? どんな提案でも大歓迎です!ありがとう

アップデート

peeskilet から提供された回答で、コンポーネントから changeDetection 行を削除したところ、機能しました。

ただし、コードをさらに作業すると、移動します

self._securityService.setAdminStatus(isAdmin);

別のサービス (この場合は Facebook サービス) に接続し、アプリ コンポーネントからそのサービスを呼び出します。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();
    }
}

これはかなり興味深いです。どうやら、angular 2 変更検出についてもっと学ぶ必要があります。どなたか良い参考書をご存知でしたら教えてください。

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

4

1 に答える 1

9

を使用しているからですchangeDetection: ChangeDetectionStrategy.OnPush@Inputこれが意味することは、コンポーネントの変更検出は、 s 入力が変更された場合にのみ発生するということです1

したがって、を削除すると@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();
    })
  }
}

1 - Angular 2 の ChangeDetectionStrategy.OnPush および Observable.subscribeも参照してください。

于 2016-10-08T03:35:44.697 に答える