Angular OnPush не обновляет шаблон

У меня есть два компонента, оба из которых имеют значение OnPush. Родительский компонент устанавливает для accountLoading значение true после вызова getAccount(), а затем устанавливает для accountLoading значение false после завершения вызова. Как и ожидалось, консоль выводит:

this.accountLoading true

с последующим:

this.accountLoading false

Тем не менее, шаблон не обновляется и застревает, думая, что accountLoading верно. Как мне заставить шаблон обновляться должным образом при изменении значения? Я бы хотел сохранить обнаружение изменений как OnPush.

Родительский компонент:

Машинопись:

public accountLoading: boolean;
...

getAccount() {
  this.accountLoading = true;
    this.authStore
        .pipe(select(fromAuthStore.getAccountData))
        .subscribe(account => {
          if (account) {
            this.accountLoading = false;
          }
          console.log('this.accountLoading', this.accountLoading);
        });

  // Loading account if it hasn't yet been loaded
  this.authService.getAccount();
}

HTML:

<child-component
  [accountLoading]="accountLoading">
</child-component>

Дочерний компонент:

Машинопись:

@Input() accountLoading: boolean;
...

HTML:

<p *ngIf="accountLoading">
  Loading...
</p>

person Bryan    schedule 24.09.2019    source источник


Ответы (3)


Попробуйте тему поведения

public accountLoading$: BehaviorSubject<boolean>(false);
...

getAccount() {
  this.accountLoading$.next(true);
    this.authStore
        .pipe(select(fromAuthStore.getAccountData))
        .subscribe(account => {
          if (account) {
            this.accountLoading$.next(false);
          }
        });

  // Loading account if it hasn't yet been loaded
  this.authService.getAccount();
}

и используйте асинхронный канал в шаблоне

<p *ngIf="accountLoading$ | async">
  Loading...
</p>

Я написал библиотеку, которая позаботится о таком управлении состоянием для вас, https://github.com/adriandavidbrand/ngx-rxcache. Прочтите об этом здесь https://medium.com/@adrianbrand/angular-state-management-with-rxcache-468a865fc3fb.

person Adrian Brand    schedule 24.09.2019

Если оба ваших компонента используют стратегию обнаружения изменений OnPush, дочерний шаблон не будет обновлен, когда родительский. Ваш дочерний компонент должен будет реализовать ловушку жизненного цикла OnChanges, и вы можете активировать обнаружение изменений там, когда значение ввода изменится.

person Apokralipsa    schedule 24.09.2019

Я бы сделал это стандартным наблюдаемым шаблоном:

public accountLoading$: Observable<boolean>;

...

getAccount() {
   this.accountLoading$ = this.authStore
        .pipe(select(fromAuthStore.getAccountData), map(account => !!account));


  // Loading account if it hasn't yet been loaded
  this.authService.getAccount();
}

HTML:

<child-component
  [accountLoading]="accountLoading$ | async">
</child-component>
person Gabriel George    schedule 24.09.2019