Angular FormControl 的 material-checkboxes.component 已选择值,但 this.controlValue 是一个空数组

Angular FormControl's material-checkboxes.component has selected values but this.controlValue is an empty array

我构建了一个 Angular 表单,其中包含一个 material-checkboxes 组件。我有这个组件的两个副本,一个是静态的,一个是动态的。唯一的区别是动态版本从 API 调用中获取其控制值。这两个示例都有一个或多个选项默认为在控件初始化时选中。

我遇到的问题是,只要动态模型保持不变,它的模型就会与其视图不同步(即,如果我不单击 select 的任何复选框控件或unselect 他们)。单击其中一个复选框后,模型会更新以与视图同步。

我可以这么说,因为我可以提交静态版本并获得预期的结果(默认项目 posted 为预期的值)。但是,当我提交动态的时,我得到一个空的 post.

在我提交组件以查看提交的表单数据之前,这是默认值组件的样子:

这是提交的结果值(符合预期):

作为比较,这里是相同的控件 (material-checkboxes.component.ts),但使用外部数据源构建以输入 titleMap,并且还具有默认值。

这是提交上述表格后的结果:

因此,如屏幕截图所示,手动创建的按预期工作并提交包含默认值的表单。但是,具有动态生成值的组件,即使视图显示它具有 selected 默认选项,也会作为 EMPTY 提交。

预期:this.controlValue = ['12', 'd4']

实际:

onInit > this.controlValue = ['12', 'd4']

updateValue 方法后 > this.controlValue = undefined // 但视图与 init

没有变化

但是,如果我手动更改任何值,我可以让它按预期提交数据,即使我完全按照默认设置设置它们。好像只有手动点击选项才会设置表单数据

这是包含组件的模板的片段:

<mat-checkbox
    type="checkbox"
    [class.mat-checkboxes-invalid]="showError && touched"
    [class.mat-checkbox-readonly]="options?.readonly"
    [checked]="allChecked"
    [disabled]="(controlDisabled$ | async) || options?.readonly"
    [color]="options?.color || 'primary'"
    [indeterminate]="someChecked"
    [name]="options?.name"
    (focusout)="onFocusOut()"
    (change)="updateAllValues($event)"
    [required]="required"
    [value]="controlValue">

更新:我发现问题是在 setTitleMap hostlistener 之后调用 syncCurrentValues() 方法之前,表单控件的值没有更新。在 syncCurrentValues() 中添加对 this.updateValue() 的调用可以解决它,并且模型和视图重新同步。但是,有一个问题,但首先,这里是在 this.options 数据中设置了默认值时解决问题的代码:

@HostListener('document:setTitleMap', ['$event'])
  setTitleMap(event: CustomEvent) {
    if (event.detail.eventName === this.options.wruxDynamicHook && isRequester(this.componentId, event.detail.params)) {
      this.checkboxList = buildTitleMap(event.detail.titleMap, this.options.enum, true, true, this.options.allowUnselect || false);
      // Data coming in after ngInit. So if this is the first time the list is provided, then use the defaultValues from the options.
      const value = this.setDefaultValueComplete ?
        this.jsf.getFormControl(this)?.value || [] :
        [].concat(this.options?.defaultValue || []);
      this.syncCurrentValues(value);
      // Set flag to true so we ignore future calls and not overwrite potential user edits
      this.setDefaultValueComplete = true;
    }
  }

updateValue(event: any = {}) {
  this.options.showErrors = true;
  // this.jsf.updateArrayCheckboxList(this, this.options.readonly ? this.checkboxListInitValues : this.checkboxList);
  this.jsf.updateArrayCheckboxList(this, this.checkboxList);
  this.onCustomAction(this.checkboxList);
  this.onCustomEvent(this.checkboxList);
  this.jsf.forceUpdates();
  if (this.jsf.mode === 'builder-properties') {
    this.jsf.elementBlurred();
  }
}

syncCurrentValues(newValues: Array<any>): void {
  for (const checkboxItem of this.checkboxList) {
    checkboxItem.checked = newValues.includes(checkboxItem.value);
  }
  this.updateValue(); // Fixed it. Otherwise, the checked items in titlemap never get synced to the model
}

上面对 updateData() 的调用解决了这种情况下的问题。但是,如果选项数据中没有默认值,并且复选框数据将从API呼叫的外部加载,该调用在ngoninit启动后执行,我也有同样的问题。 this.controlValue 在 ngOnInit 之后为空,尽管视图已更新以显示选中的复选框。该模型通过 setTitleMap() 方法实现了这一点,但 controlValue 仍记录为空数组。