Угловая асинхронная труба для свойства Input в дочернем компоненте не установлена - PullRequest
0 голосов
/ 01 февраля 2019

Кажется, что дочерний компонент устанавливается только при первом запуске Observable.

Контейнерный компонент (добавлен оператор карты для отладки):

this.form$ = this.createOrderStore.pipe(select(getFormGroup)).pipe(
  tap((val) => {
    console.log('observable emitted');
    console.log(val);
    return val;
  })
);

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

private _form: FormGroup;
@Input()
set form(val) {
  console.log('set form');
  if (val) {
    this._form = val;
  }
}
get form() {
  return this._form;
}

Шаблон контейнера:

<app-order-form [form]="form$ | async"></app-order-form>

В первый раз, когда наблюдаемое излучает, консоль показывает «наблюдаемое излученное», значение val не определено, затем «задайте форму».Однако, так как это первое значение не определено, мы еще не установили его в шаблоне.

Во второй раз, когда наблюдаемое излучает, консольные журналы 'наблюдаемые испускаются', val является полной группой форм (поэтомуобнаружение изменения триггера), но «заданная форма» не регистрируется.Это второе значение, которое мне действительно нужно установить в шаблоне.

Есть ли причина, по которой свойство дочернего компонента устанавливается только в первый раз, когда наблюдаемое излучает?

1 Ответ

0 голосов
/ 01 февраля 2019

Я считаю, что ваша проблема возникает только тогда, когда у вас есть от ChangeDetectionStrategy до OnPush.Вы устанавливаете this.form$, вероятно, в хук ngAfterViewInit, из-за метода getFormGroup, я прав?Есть два способа обойти это.

Простой способ, используя ChangeDetectorRef

Контейнерный компонент:

constructor(readonly cd: ChangeDetectorRef) {}

ngAfterViewInit(): void {
   // ...

   this.form$ = this.createOrderStore.pipe(select(getFormGroup));
   this.cd.markForCheck();
}

Другим способом является использование Subject, чтобыобновите formGroup, и у вас уже будет определено forms$ при построении класса с использованием

formGroup$ = new ReplaySubject<FormGroup>(1);

readonly form$ = this.formGroup$.pipe(
  mergeMap((formGroup) => this.createOrderStore.pipe(
    select(formGroup)
  ))
);

ngAfterViewInit(): void {
   // ...
   this.formGroup$.next(getFormGroup);
}

Просто для выяснения того, что происходит в вашем коде в данный момент, это то, что свойство form$ компонента контейнера имеет видне определено.Это неопределенное, что вы регистрируете в своем дочернем компоненте, и поскольку вы устанавливаете form$ внутри хука ngAfterViewInit, он не будет обнаружен детектором изменений, если вы специально не попросите его проверить

...