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 仍记录为空数组。
我构建了一个 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 仍记录为空数组。