0

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

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

我可以告诉这一点,因为我可以提交静态版本并获得预期的结果(默认项目按预期作为值发布)。但是,当我提交动态的时,我得到一个空帖子。

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

在此处输入图像描述

这是结果提交的值(如预期的那样):

在此处输入图像描述

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

在此处输入图像描述

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

在此处输入图像描述

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

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

实际的:

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

updateValue 方法后 > this.controlValue = undefined // 但是视图从初始化开始没有变化

但是,如果我手动更改任何值,我可以让它按预期提交数据,即使我将它们完全设置为默认值。就好像在手动单击选项之前没有设置表单数据。

以下是包含该组件的模板的片段:

<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">
4

1 回答 1

0

更新:我发现问题是表单控件的值在离开 setTitleMap 主机监听器之后调用的 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() 的调用解决了这种情况下的问题。However, when there are no default values in the options data and the checkbox data is loaded externally from an API call that executes after the ngOnInit has fired, I have the same issue. 尽管视图已更新为显示选中的复选框,但在 ngOnInit 之后 this.controlValue 为空。该模型通过 setTitleMap() 方法实现了这一点,但 controlValue 仍记录为空数组。

于 2021-09-15T18:50:50.967 回答