角度嵌套反应形式 registeronchange 错误

时间:2021-05-25 19:07:36

标签: angular angular-forms

我正在尝试实现角度反应嵌套表单。我的表单工作正常,但在加载表单时 我收到以下错误。我的表单正在正确验证,我能够访问我的嵌套值。但在 初始加载我收到以下错误,因为它没有正确呈现。

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 错误。任何帮助将不胜感激!!!

0 个答案:

没有答案