简体   繁体   中英

Angular2: No value accessor for a nested form

I'e created a form with a nested form group:

this.cardForm = this.fb.group({
    number: ['', Validators.compose([Validators.required, this.validateCardNumber])],
    holderName: ['', Validators.required],
    expiry: this.fb.group({
      expirationMonth: ['', Validators.required],
      expirationYear: ['', Validators.required],
    }, this.validateCardExpiry),
    cvc: ['', Validators.required]
});

Into my template:

<form [formGroup]="cardForm" novalidate="novalidate" (ngSubmit)="onSave()"> 
    <div class="form-group" formGroupName="expiry">
        <label for="expirationmonth">Expiration month</label>
        <select2 id="default-select"
                name="expirationmonth"
                formControlName="expirationMonth"
                [data]="months$ | async"
                [width]="250"
                [options]="select2Options">
        </select2>
        <label for="expirationyear">Expiration year</label>
        <select2 id="default-select2"
                name="expirationyear"
                formControlName="expirationYear"
                [data]="years$ | async"
                [width]="250"
                [options]="select2Options">
        </select2>
    </div>
</form>

select2 is a component from ng2-select2 .

Angular is getting me this message:

Error: No value accessor for form control with path: 'expiry -> expirationMonth'

This seems to be an issue with forms, as per this from the GitHub issues

So you'd have to do some workaround for this currently. As per last comment on that issue you could try what has been done:

I spent sometime to figure out using with reactive form. All I had to do was implement implement ControlValueAccessor and propagate change from ngAfterViewInit on select/unselect.

Playing around with your code, another workaround that I found was to use ngDefaultControl on the selects.

<select2 ngDefaultControl ..... ></select2>

But with this rises the problem, that when you make changes, it's not reflected in the form values. So a quick workaround for that would be to patchValue when values change. This might not be pretty, but works.

Template using the ng2-select2's change event:

(valueChanged)="changed($event)"

Component to patch one of the values:

changed(e) {   // e is of primitive type here
  this.cardForm.controls['expiry'].controls['expirationMonth'].patchValue(e)
}

尝试将ngControlDefault添加到您的<div>

<div class="form-group" formGroupName="expiry" ngControlDefault>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM