javascript - 未设置子组件中输入属性的 Angular 异步管道

标签 javascript angular typescript rxjs ngrx

看起来子组件仅在 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 是一个完整的表单组(因此它应该触发更改检测),但不会记录“设置表单”。第二个值是我实际需要在模板中设置的值。

仅在可观察对象第一次发出时才设置子组件属性是否有原因?

最佳答案

我相信只有当您将 ChangeDetectionStrategy 更改为 OnPush 时,才会出现您的问题。由于 getFormGroup 方法,您可能在 ngAfterViewInit Hook 中设置 this.form$ ,对吗?有两种方法可以解决这个问题。

简单的方法,使用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$ 属性未定义。这是您在子组件中登录的未定义,并且因为您在 ngAfterViewInit Hook 内设置 form$,所以它不会被更改检测器拾取,除非你特意告诉它去检查

关于javascript - 未设置子组件中输入属性的 Angular 异步管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54484186/

相关文章:

typescript - 声明一个充当起始点为 1 的数组的接口(interface)

javascript - 尽管文件存在,但获取 'Module not found'

javascript - 如何解决 jquery-mobile 的页面导航问题

javascript - Express js 4x :req. 参数返回空对象

database - 路由时应该保留数据吗?

unit-testing - Ionic 2 NavController 单元测试

html - 卡片组件内的 Bootstrap 4 按钮具有单击事件

javascript - GreenSock 和 TypeScript

javascript - jQuery:用于延迟 removeClass() 的脚本延迟时间太长

javascript - Kendo UI 网格不会触发创建、更新和销毁事件