angular - 角度嵌套反应形式 registeronchange 错误
问题描述
我正在尝试实现角度反应嵌套形式。我的表单工作正常,但在表单加载时出现错误。我的表单正在正确验证,我能够访问我的嵌套值。但是在初始加载时,我收到以下错误,因此它没有正确呈现。
ERROR TypeError: control.registerOnChange is not a function
at setUpModelChangePipeline (forms.js:1689)
at setUpControl (forms.js:1511)
at FormGroupDirective.addControl (forms.js:5253)
at FormControlName._setUpControl (forms.js:5835)
at FormControlName.ngOnChanges (forms.js:5780)
at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.js:1520)
at callHook (core.js:2583)
at callHooks (core.js:2542)
at executeInitAndCheckHooks (core.js:2493)
at selectIndexInternal (core.js:8463)
父组件 HTML
<form [formGroup]="studentForm">
<h4>Student Details</h4>
<mat-form-field>
<label>Name</label>
<input matInput type="text" name="name" formControlName="name"><br>
<mat-error *ngIf="name.errors?.required">Name is required</mat-error>
<mat-error *ngIf="name.errors?.minlength">Name should be minimum {{name.errors?.minlength.requiredLength}} characters</mat-error>
<mat-error *ngIf="name.errors?.maxlength">Name should be maximum {{name.errors?.maxlength.requiredLength}} characters</mat-error>
</mat-form-field>
<br>
<mat-form-field>
<label>Age</label>
<input matInput type="text" formControlName="age"><br>
<mat-error *ngIf="age.errors?.required">Age is required</mat-error><br>
</mat-form-field>
<ng-container *ngIf="age.errors | displayOneError: ['required','minlength','minor'] as error">
<div *ngIf="error?.minlength">Age should be minimum {{error?.minlength.requiredLength}} characters</div><br>
<div *ngIf="error?.minor">Age should be greater than 18</div><br>
</ng-container>
<br>
<!-- {{age.errors | json}} -->
<mat-form-field>
<label>Email</label>
<input matInput type="text" formControlName="email"><br>
<mat-error *ngIf="email.errors?.required">Email is required</mat-error>
<mat-error *ngIf="email.errors?.email">Email is invalid</mat-error>
</mat-form-field>
<br>
<app-addresscomponent formControlName="addressForm"></app-addresscomponent>
<input type="button" value="Submit" [disabled]="!studentForm.valid" (click)="save()"/>
{{studentForm.value | json}}
{{studentForm.errors | json}}
</form>
Parent Component TS
import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { ApiBuilderService } from '../builder/api-builder-service';
import { Student } from '../model/student';
import { createMinorAgeValidator } from '../validators/age-validator';
@Component({
selector: 'app-embeddedform',
templateUrl: './embeddedform.component.html',
styleUrls: ['./embeddedform.component.scss']
})
export class EmbeddedformComponent implements OnInit {
studentForm = this.fb.group({
name : ['',{
validators : [Validators.required, Validators.minLength(3), Validators.maxLength(50)],
updateOn : 'blur'
}],
age : ['', {
validators : [Validators.required, Validators.minLength(2), createMinorAgeValidator()],
updateOn : 'blur'
}],
email : ['', {
validators : [Validators.required, Validators.minLength(3), Validators.maxLength(50)],
updateOn : 'blur'
}],
addressForm : this.fb.group({
city : ['',{
validators : [Validators.required, Validators.minLength(3), Validators.maxLength(50)],
updateOn : 'blur'
}],
state : ['', {
validators : [Validators.required, Validators.minLength(3), Validators.maxLength(50)],
updateOn : 'blur'
}],
})
});
constructor(private fb : FormBuilder, private apiBuilderService : ApiBuilderService) { }
ngOnInit(): void {
}
get name() {
return this.studentForm.controls['name'];
}
get age() {
return this.studentForm.controls['age'];
}
get email() {
return this.studentForm.controls['email'];
}
save() {
let student : Student = {...this.studentForm.getRawValue()};
alert(JSON.stringify(student));
alert(JSON.stringify(this.apiBuilderService.buildStudentRequest(student)));
}
}
Child Component:
import { Component, forwardRef, OnDestroy, OnInit, StaticProvider } from '@angular/core';
import { Validators, FormBuilder, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, RequiredValidator, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
import { Subscription } from 'rxjs';
import { Address } from '../model/address';
@Component({
selector: 'app-addresscomponent',
templateUrl: './addresscomponent.component.html',
styleUrls: ['./addresscomponent.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi:true,
useExisting: AddresscomponentComponent
},
]
})
export class AddresscomponentComponent implements OnInit, ControlValueAccessor,OnDestroy, Validator {
addressForm = this.fb.group({
city : ['',{
validators : [Validators.required, Validators.minLength(3), Validators.maxLength(50)],
updateOn : 'blur'
}],
state : ['', {
validators : [Validators.required, Validators.minLength(3), Validators.maxLength(50)],
updateOn : 'blur'
}],
});
onTouched = () => {};
onValidated = () => {};
onChangeSub: Subscription;
constructor(private fb : FormBuilder) { }
validate(control: AbstractControl): ValidationErrors {
return this.addressForm.valid? null:{invalidForm : { valid : false, message : "Invalid Address Form"}};
}
registerOnValidatorChange?(onValidated: () => void): void {
this.onValidated = onValidated;
}
ngOnDestroy(): void {
this.onChangeSub.unsubscribe();
}
writeValue(value: any): void {
if (value) {
this.addressForm.setValue(value);
}
}
registerOnChange(onChange: any): void {
this.onChangeSub = this.addressForm.valueChanges.subscribe(onChange);
}
registerOnTouched(onTouched: any): void {
this.onTouched = onTouched;
}
setDisabledState(disabled:boolean) {
if (disabled) {
this.addressForm.disable();
}
else {
this.addressForm.enable();
}
}
}
Child Component Html
<form [formGroup]="addressForm">
<h4>Address Details</h4>
<mat-form-field>
<label>City</label>
<input matInput type="text" name="city" formControlName="city" (blur)="onTouched()"><br>
<mat-error *ngIf="city.errors?.required">City is required</mat-error>
<mat-error *ngIf="city.errors?.minlength">City should be minimum {{city.errors?.minlength.requiredLength}} characters</mat-error>
<mat-error *ngIf="city.errors?.maxlength">City should be maximum {{city.errors?.maxlength.requiredLength}} characters</mat-error>
</mat-form-field>
<br>
<mat-form-field>
<label>State</label>
<input matInput type="text" name="state" formControlName="state" (blur)="onTouched()"><br>
<mat-error *ngIf="state.errors?.required">State is required</mat-error>
<mat-error *ngIf="state.errors?.minlength">State should be minimum {{state.errors?.minlength.requiredLength}} characters</mat-error>
<mat-error *ngIf="state.errors?.maxlength">State should be maximum {{state.errors?.maxlength.requiredLength}} characters</mat-error>
</mat-form-field>
<br>
</form>
为什么我在加载时收到 registerOnChange 错误。任何帮助将不胜感激!!!
解决方案
推荐阅读
- forms - 表单输入验证,仅允许存在于另一个表中的值 - Acess
- python - 在python中替换文件中的字符串?
- javascript - 为 monaco-editor 添加 vue js 语言支持
- command-line - 分解变量并将其部分保存在 Windows 命令行脚本中
- webpack - 如果在监视模式下以最小输出运行,如何将当前时间戳添加到 webpack4 中的输出
- c++ - VSCode 动态链接 - C++ Boost 测试
- jquery - 添加 alt 标签 jQuery
- php - 如何在 echo 语句中更改变量的内容
- spring-boot - 有没有更好的方法来构造一个可能不需要的具有多个参数的控制器?
- c++ - 如何为模板低音类的所有实例化创建共享静态变量?