Angular react 形式数组,更改检测覆盖形式

标签 angular formarray

我使用过以下question作为我 FormArray 表单设计的基础。我想做的事情的要点是使表单与页面上其他地方的更改保持最新,但在此表单中切换 bool 值/复选框。 (用户有一个他们选择的卡片列表,此表单显示了此选择的列表)

不幸的是,ngOnChanges似乎在不断更新表单,而我的更改正在被覆盖。在我的构造函数中,我检测值更改,并意图发出这些更改。然而,

this.contextSummaryForm.dirty

始终为假。 rebuildForm() 上的断点表明该方法每秒被调用多次 - 因此将 contextItem.isEditEnable 更改为 false 被完全覆盖。我可以阅读我的逻辑并了解为什么会发生这种情况 - 但我真的不明白我应该做什么来允许从其父组件更新 contextList 并允许用户在此处更新表单。

构造函数和更改检测

@Input()
contextList: ContextItem[];

@Output()
contextListChange  = new EventEmitter<any>();

valueChangeSubscription = new Subscription;
contextSummaryForm: FormGroup;
isLoaded: boolean = false;


constructor(protected fb: FormBuilder) {
   this.createForm();


   this.valueChangeSubscription.add(
         this.contextSummaryForm.valueChanges
         .debounceTime(environment.debounceTime)
           .subscribe((values) => {
           if (this.isLoaded && this.contextSummaryForm.valid && this.contextSummaryForm.dirty) {

             this.contextSummaryForm.value.plans.forEach(x => {
               var item = this.contextList.find(y => y.plan.id === x.id);
               item.isEditEnabled = x.isEditEnabled;
             });

             this.contextListChange.emit(this.contextList);
             this.contextSummaryForm.markAsPristine();
           }
         }));
     }

表单创建:

createForm(): void {
 this.contextSummaryForm = this.fb.group({
  plans: this.fb.array([this.initArrayRows()])
 });
}

initArrayRows(): FormGroup {
  return this.fb.group({
   id: [''],
   name: [''],
   isEditEnabled: [''],
});
}

OnChanges

  ngOnChanges(changes: SimpleChanges) {
for (let propName in changes) {
  if (propName === 'contextList') {
    if (this.contextList) {
      this.rebuildForm();
      this.isLoaded = true;
    }
  }
}
}

rebuildForm() {
  this.contextSummaryForm.reset({
  });
  //this.fillInPlans();
  this.setPlans(this.contextList);
}


  setPlans(items: ContextItem[]) {
    let control = this.fb.array([]);
    items.forEach(x => {
      control.push(this.fb.group({
        id: x.plan.id,
        name: x.plan.Name,
        isEditEnabled: x.isEditEnabled,
      }));
    });
    this.contextSummaryForm.setControl('plans', control);
  }

总结一下:我需要一种使用从输入绑定(bind)构建的表单数组的方法,该方法可以跟上变化而不会快速覆盖表单。

最佳答案

根据 Angular 的文档

OnChanges: A lifecycle hook that is called when any data-bound property of a directive changes

话虽如此,覆盖表单的不是更改检测,也不是 onChanges Hook 。作为最佳实践,我们应该只构建一次表单并使用 FormArray 的方法来干扰数组

您可以利用 FormArray 方法并直接在数组上push 项,而不是重建表单。我认为您面临的问题是您正在重建表单,无论数据是什么。

我的意思是:认为你有两个组件。 child 和家长。子级负责操作数据(添加、删除),父级负责在表单上显示这些数据。虽然这样做看起来很简单,但您必须过滤掉子组件已经处理过的所有项目。

在您的实现中,尽量不要在 onChanges 上重建表单,而是将项目推送到数组上。

您应该将哪些项目推送到数组? (过滤掉所有已经处理过的项目)

const contextItemsToInsert = 
          this.contextList.filter((it: any) => !this.plans.value.map(pl => pl.id).includes(it.id));

这是一种可以解决您的问题的方法

ngOnChanges(changes: SimpleChanges) {
    for (let propName in changes) {
      if (propName === 'contextList') {

        const contextItemsToInsert = 
          this.contextList.filter((it: any) => !this.plans.value.map(pl => pl.id).includes(it.id));

            contextItemsToInsert.forEach((x: any) => {

              this.plans.push(this.fb.group({
                id: x.id,
                name: x.name,
                isEditEnabled: x.isEditEnabled,
              }))
            })

            // similar approach for deleted items
      }
    }
  }

  ngOnInit() {
    this.createForm();
  }

  createForm(): void {
    this.contextSummaryForm = this.fb.group({
      plans: this.fb.array([this.initArrayRows()])
    });
  }

  initArrayRows(): FormGroup {
      return this.fb.group({
        id: [''],
        name: [''],
        isEditEnabled: ['']
    });
  }

在这里您可以找到一个工作示例 https://stackblitz.com/edit/stackoverflow-53836673

这不是一个完整的示例,但它有助于理解问题的要点。

我希望我正确理解您面临的问题是什么

关于 Angular react 形式数组,更改检测覆盖形式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53836673/

相关文章:

Angular 2 : Cannot find form control at index 1 at FormArray

javascript - 类型 'xxx' 上不存在属性 '{}'

javascript - src/app/app-routing.module.ts(10,11) : error TS1005: ',' expected 中的错误

angular - 使用 Angular FormArray 计算值

angular6 - 为什么 Angular ReactiveForms FormArray 会抛出错误 "TypeError: Cannot read property ' updateOn' of null”

html - 这种 jpeg 数据是什么?如何将其用作图像标签 src 以在网页中显示它?

html - Angular 9 : html select does respect value in model after click

http - Angular 2 - 检查来自订阅的服务器错误

angular - FormArray 动态形式angular