gpt4 book ai didi

angular - 从 json 创建动态表单时出错找不到名称为 : 'data' 的控件

转载 作者:太空狗 更新时间:2023-10-29 17:50:55 25 4
gpt4 key购买 nike

我正在使用 Angular 7 应用程序,我正在编写一个通用的动态表单创建器。我正在使用 react 形式和 ng-template and <ng-container *ngTemplateOutlet>用于递归显示表单元素。项目代码可见Here .

但是我遇到了以下错误

ERROR Error: Cannot find control with name: 'data'
at _throwError (forms.js:1775)
at setUpControl (forms.js:1683)
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.addControl (forms.js:4532)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName._setUpControl (forms.js:5030)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName.ngOnChanges (forms.js:4980)
at checkAndUpdateDirectiveInline (core.js:9239)
at checkAndUpdateNodeInline (core.js:10507)
at checkAndUpdateNode (core.js:10469)
at debugCheckAndUpdateNode (core.js:11102)
at debugCheckDirectivesFn (core.js:11062)

但是如果我看到我的 formGroup 对象,我可以看到一个控件,其中数据作为控件的名称,如下所示。

enter image description here

我做错了什么?请帮忙。

问题的再现是Here stackblitz

最佳答案

你说得对,这里的 ng-template 有问题。

FormControlName 指令在很大程度上依赖于当前元素之上元素的层次结构来确定 FormControl。由于您使用的是 ngTemplateOutlet,这个层次结构混淆了,Angular 无法找到父级 FormGroupFormArray 控件。

您可以重构您的示例以使用嵌套组件,如果您保留子 AbstractControls 的层次结构,它应该可以工作。

另一方面,如果您要使用 FormControl,则可以使它与 ngTemplateOutlet 一起使用指示。您只需确保为 input 元素提供了正确的控制。

具体做法如下:

<form [formGroup]="form">
<ng-container *ngTemplateOutlet="controlList; context: {controls: schema, path: []}"></ng-container>

<ng-template #controlList let-controls="controls" let-path="path" let-isArray="isArray">

<ng-container *ngFor="let control of controls; let i = index;">
<ng-container *ngIf="control?.type === 'simple'">
<div class="control">
<label>
{{ control.label }}
<input type="text" [formControl]="form.get(isArray ? path.concat(i, control.name) : path.concat(control.name))">
</label>
</div>
</ng-container>
<ng-container *ngIf="['object', 'array'].indexOf(control.type) > -1">
<fieldset>
<legend>{{control.name}}</legend>
<ng-container
*ngTemplateOutlet="controlList; context: {controls: control.items, isArray: control.type === 'array', path: isArray ? path.concat(i, control.name) : path.concat(control.name)}">
</ng-container>
</fieldset>
</ng-container>
</ng-container>

</ng-template>
</form>

这里的关键点是获取目标控件的正确路径,我将其作为上下文的一部分传递给下一个子级别。

此外,如果您想生成无限结构嵌套元素,您应该重构构建 FormGroup 的代码:

ngOnInit() {
this.schema = data.start.fields.schema;
this.form = this.createFormGroup(this.schema);
}

createFormGroup(items) {
let group: { [controlId: string]: AbstractControl; } = {};

items.forEach((item) => group[item.name] = this.createFormControl(item));

return this.fb.group(group);
}

createFormControl(item) {
if (item.type === 'array') {
return this.fb.array(item.items.map((subItem) => {
return this.fb.group({
[subItem.name]: this.createFormControl(subItem)
})
}));
} else if (item.type === 'object') {
return this.createFormGroup(item.items);
} else {
return this.fb.control(item.value, []);
}
}

Ng-run Example

关于angular - 从 json 创建动态表单时出错找不到名称为 : 'data' 的控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56806982/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com