我有一个使用反应形式方法的表格。表单在我的哈巴狗中创建如下:
form([formGroup]='form', novalidate='', (ngSubmit)='postSurvey(form.value, form.valid)')
除非我尝试在javascript部分中更改表单(FormArray
),否则一切正常。我收到以下错误:
EXCEPTION: Error in http://localhost:8080/app/components/fillForm.template.html:0:326 caused by: control.registerOnChange is not a function
core.umd.js:3497 TypeError: control.registerOnChange is not a function
at setUpControl (http://localhost:8080/node_modules/@angular/forms/bundles/forms.umd.js:1634:17)
at eval (http://localhost:8080/node_modules/@angular/forms/bundles/forms.umd.js:4752:25)
at Array.forEach (native)
at FormGroupDirective._updateDomValue (http://localhost:8080/node_modules/@angular/forms/bundles/forms.umd.js:4747:29)
at FormGroupDirective.ngOnChanges (http://localhost:8080/node_modules/@angular/forms/bundles/forms.umd.js:4616:22)
at Wrapper_FormGroupDirective.ngDoCheck (/ReactiveFormsModule/FormGroupDirective/wrapper.ngfactory.js:30:18)
at View_FillFormComponent2.detectChangesInternal (/AppModule/FillFormComponent/component.ngfactory.js:275:32)
at View_FillFormComponent2.AppView.detectChanges (http://localhost:8080/node_modules/@angular/core/bundles/core.umd.js:12592:18)
at View_FillFormComponent2.DebugAppView.detectChanges (http://localhost:8080/node_modules/@angular/core/bundles/core.umd.js:12739:48)
at ViewContainer.detectChangesInNestedViews (http://localhost:8080/node_modules/@angular/core/bundles/core.umd.js:12850:41)
at CompiledTemplate.proxyViewClass.View_FillFormComponent0.detectChangesInternal (/AppModule/FillFormComponent/component.ngfactory.js:64:14)
at CompiledTemplate.proxyViewClass.AppView.detectChanges (http://localhost:8080/node_modules/@angular/core/bundles/core.umd.js:12592:18)
at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost:8080/node_modules/@angular/core/bundles/core.umd.js:12739:48)
at CompiledTemplate.proxyViewClass.AppView.internalDetectChanges (http://localhost:8080/node_modules/@angular/core/bundles/core.umd.js:12577:22)
at CompiledTemplate.proxyViewClass.View_FillFormComponent_Host0.detectChangesInternal (/AppModule/FillFormComponent/host.ngfactory.js:29:19)
我更改表单的代码非常复杂,我无法简化它或在plunker中重现它。不仅仅是直接找到解决方案(由于细节太少而太难),我想了解这个错误意味着什么?什么可能导致这个错误。
我已经发现错误发生在我的HTML中的[formGroup]='form'
。
任何建议都会有所帮助。
答案 0 :(得分:26)
是的,该错误消息有点神秘,但是如果您使用 FormBuilder ,当您在组件中向 FormGroup 添加控件并将其命名为时,您会看到此信息“A”,但是忘记将 formControlName =“A”的输入添加到模板中,或 formControlName 表示预期的输入不是 A ,或为空,或不存在。
基本上,它说:“我无法将FormGroup中的控件与模板中的控件匹配”。
答案 1 :(得分:21)
在我的情况下,抛出此错误是因为我使用FormControlName
而不是FormArrayName
绑定到模板中的FormArray
。
我的组件代码:
public form = new FormGroup({
...
checkboxes: new FormArray([....])
})
抛出错误的模板代码:
<input type="checkbox" formControlName="checkboxes" />
修复:
<input type="checkbox" formArrayName="checkboxes" />
答案 2 :(得分:19)
我遇到了寻找类似问题的解决方案,然后自己找到了解决方案。 我的问题如下。我有一个这样的表格
form: FormGroup = new FormGroup({
status: new FormArray([])
});
最初,它由模板上每个状态的复选框列表表示。然后我创建了一个自定义组件来表示status
选择器,并在模板中使用它,如此
<status-selector [formControlName]="'status'"></status-selector>
问题是formControlName
必须指向FormControl
实例,但实际上它指向FormArray
实例。因此,更改为status: new FormControl([])
可以解决此问题。
答案 3 :(得分:7)
在我的情况下,当formControl名称与页面上的模板变量相同时发生错误。例如
<select id="status" [formControl]="userStatus">...</select>
<form-status #userStatus ></form-status> //matching template variable name
答案 4 :(得分:4)
当混合模板驱动与反应驱动方法(错误)混合时,我也遇到了此错误:
<input #inputCtrl
[formControl]="inputCtrl"
/>
inputCtrl
已在组件中正确定义。当然,#inputCtrl
必须报废才能正常工作(很难看到输入何时具有约10个属性)。
答案 5 :(得分:2)
this.extensionForm = this._fb.group({
id: [''],
category: [12],
extensions: new FormArray([]),
priority: ['', []],
});
formArray.push(this.extensionForm);
<块引用>
注意:- 错误是因为您使用了 formControlName 在你声明 formArray 的地方,你必须使用 formArrayName 来代替
<input type="text" formControlName="extensions" />
simple solution:
<input type="checkbox" formArrayName="extensions" />
答案 6 :(得分:1)
也许您已将控件元素移到模板中的组外。
行:
<div formGroupName="passwordForm">
Password: <input type="password" formControlName="password">
Confirm: <input type="password" formControlName="confirmPassword">
</div>
不行:
Password: <input type="password" formControlName="password">
<div formGroupName="passwordForm">
Confirm: <input type="password" formControlName="confirmPassword">
</div>
答案 7 :(得分:1)
对于未来的读者,我的问题很简单,它会导致 TypeError: control.registerOnChange is not a function
当我创建新的 FormGroup 时,我不小心使用了 FormGroup 而不是 FormControl
myForm: FormGroup = new FormGroup({
lname: new FormGroup({}),
fnam: new FormGroup({}),
date: new FormGroup({}),
});
应该是这样的:
myForm: FormGroup = new FormGroup({
lname: new FormControl(''),
fnam: new FormControl(''),
date: new FormControl(null),
});
希望这会在未来为某人节省几分钟!
答案 8 :(得分:1)
在 Angular 中,当我尝试构建自己的表单组件并忘记实现 ControlValueAccessor 接口时遇到了同样的问题:
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'my-country-select',
templateUrl: './country-select.component.html',
styleUrls: ['./country-select.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CountrySelectComponent),
multi: true,
},
],
})
export class CountrySelectComponent implements OnInit, OnChanges, ControlValueAccessor {
propagateChange = (_: any) => { }; // ControlValueAccessor
private internalValue: string | undefined;
get value(): string | undefined {
return this.internalValue;
}
set value(value: string | undefined) {
this.internalValue = value;
this.propagateChange(value);
}
// some other methods here
// implementing the ControlValueAccessor interface with these three methods
writeValue(obj: any): void {
if (obj) {
this.value = obj;
}
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
// throw new Error('Method not implemented.');
}
}
答案 9 :(得分:0)
当我们在ng-template
中与*ngIf
一起使用反应形式时,也会出现此错误。
为避免这种情况,请使用ng-container
,不要使用ngElse
。
答案 10 :(得分:0)
添加造成我情况的原因。
.ts
文件,
...
export class MyComponent {
dateFrom = new FormControl(new Date());
...
}
.html
文件,
<mat-form-field>
<input matInput [matDatepicker]="dateFrom" [formControl]="dateFrom"
placeholder="Min date">
<mat-datepicker-toggle matSuffix [for]="dateFrom"></mat-datepicker-toggle>
<mat-datepicker #dateFrom ></mat-datepicker>
</mat-form-field>
基本上,在模板文件中,它不知道要选择哪个“ dateFrom”,而是在模板文件中选择一个,而不是我的打字稿文件中的FormControl
,它是{{ 1}}元素。
将FormControl重命名为mat-datepicker
可以解决此问题,
即
dateFromCtrl
...
export class MyComponent {
dateFromCtrl = new FormControl(new Date());
...
}
文件,
.html
按预期工作。
Kodos使用VS Code来解决这个问题。通过执行Cmd +单击 <mat-form-field>
<input matInput [matDatepicker]="dateFrom" [formControl]="dateFromCtrl"
placeholder="Min date">
<mat-datepicker-toggle matSuffix [for]="dateFrom"></mat-datepicker-toggle>
<mat-datepicker #dateFrom ></mat-datepicker>
</mat-form-field>
上的初始'dateFrom',我朝着这个方向发展,它使我指向[formControl]="dateFrom"
元素。
答案 11 :(得分:0)
对我来说,发生在我从自动完成输入中使用相同的[formControl]="carBrand"
和[matAutocomplete]="carBrandAuto"
我改变了
从:
...
<input
[formControl]="carBrand"
[matAutocomplete]="carBrand"
>
<mat-autocomplete matAutocomplete #carBrand="matAutocomplete">
...
TO
...
<input
[formControl]="carBrand"
[matAutocomplete]="carBrandAuto"
>
<mat-autocomplete matAutocomplete #carBrandAuto="matAutocomplete">
...
答案 12 :(得分:0)
就我而言,当实际表单模型是 FormGroup 实例时,当我在模板中使用 formControlName
时出现错误。更改为 formControlGroup
有帮助。
答案 13 :(得分:-1)
如果在表单中定义了FormArray字段,请注意,您无需使用formControlName =“”对其进行标签。您需要以其他方式(设置程序,获取程序,函数)来处理输入和验证,但是如果您尝试将formControlName分配给FormArray,肯定会出错!