admin管理员组文章数量:1421749
Problem
Given the following form:
<form [formGroup]="additional_providers_form">
<div formArrayName="providers">
@for(provider of providers.controls; track provider; let i = $index) {
<div class="row" [formGroupName]="i">
<div class="col mb-3">
<app-form-control
type="text"
label="Provider Name"
formControlName="provider_name"
[required]="true"
></app-form-control>
</div>
<div class="col mb-3">
<app-form-control
type="text"
label="Provider License"
formControlName="provider_license"
[required]="true"
></app-form-control>
</div>
</div>
}
</div>
<div class="col text-center">
<div class="d-grid gap-2">
<button type="submit" class="btn btn-black btn-lg btn-primary rounded-0 mt-5">
Save and Complete
</button>
</div>
</div>
</form>
I am trying to dynamically create an array list of components for a user to add or remove information for an application. At this point I am working on initializing the form components.
You will see my attempt to initialize the form in the following template, on line 19 and upon initialization create the first element (FormGroup) in the form array.
import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-additional-providers',
standalone: true,
imports: [ReactiveFormsModule],
templateUrl: './additional-providersponent.html',
styleUrl: './additional-providersponent.scss'
})
export class AdditionalProvidersComponent {
additional_providers_form!: FormGroup
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.additional_providers_form = this.fb.group({
providers: this.fb.array([this.createProvider()])
})
}
get providers(): FormArray {
return this.additional_providers_form.get('providers') as FormArray
}
addProvider() {
this.providers.push(this.createProvider())
}
removeItem(idx: number) {
this.providers.removeAt(idx)
}
private createProvider() {
return this.fb.group({
provider_name: [''],
provider_license: ['']
})
}
}
The formControl
objects for the above component are located within the custom component app-form-control
given here:
import { CommonModule } from '@angular/common';
import { Component, forwardRef, Input, OnChanges, OnInit, Optional, Self, SimpleChanges } from '@angular/core';
import { ControlContainer, FormControl, FormGroupDirective, FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgControl, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-form-control',
standalone: true,
imports: [ReactiveFormsModule],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FormControlComponent),
multi: true
}
],
templateUrl: './form-controlponent.html',
styleUrl: './form-controlponent.scss'
})
export class FormControlComponent implements OnInit, OnChanges {
@Input() type: string = 'text'
@Input() label: string = ''
@Input() placeholder: string = ''
@Input() isValid: boolean = false
@Input() required: boolean = false
value: any
disabled: boolean = false;
private touched = false
dirty = false
onTouched: any = () => {}
constructor(@Optional() @Self() public ngControl: NgControl) {
if (this.ngControl != null) {
this.ngControl.valueAccessor = this
}
}
ngOnInit() {
}
onChange: any = (value: boolean) => {}
ngOnChanges(changes: SimpleChanges): void {
}
registerOnTouched(fn: any) {
this.onTouched = fn
}
registerOnChange(fn: any) {
this.onChange = fn;
}
valueChanged(value: any) {
this.onChange(value)
this.markAsTouched()
this.markAsDirty()
}
writeValue(value: any) {
this.value = value
}
setDisabledState(isDisabled: boolean) {
this.disabled = isDisabled
}
private markAsTouched(): void {
if(!this.touched) {
this.touched = true
this.onTouched()
}
}
private markAsDirty(): void {
if(!this.dirty) {
this.dirty = true
}
}
}
with the html template here:
<label
class="form-label required"
[class.required]="required">{{label}}</label>
<input
#val
[type]="type"
class="form-control"
[formControl]="ngControl?.control"
[class.is-invalid]="dirty && !isValid"
[class.is-isvalid]="dirty && isValid"
(change)="valueChanged(val.value)"/>
When trying to initialize the form in this capacity I am receiving the following error:
main.ts:7 ERROR RuntimeError: NG01203: No value accessor for form control path: 'providers -> 0 -> provider_license'.
I know what the error means and why it is happening, however I do not know how to fix it.
Knowns
The error is being cause by the custom form element because it doesn't recognize that it is a control component
The error is being thrown because the Component is being created dynamically in a for loop
Attempted Solutions
The first potential solution I found was based on an answer to the following question. You will see in the app-form-control
template where I added [formControl]="ngControl?.control"
and in the typescript I added:
constructor(@Optional() @Self() public ngControl: NgControl) {
if (this.ngControl != null) {
this.ngControl.valueAccessor = this
}
}
The idea was to use the standalone approach and give it access to the ValueAccessor without worrying about the parent wrapper, but that failed.
Another solution was putting the inputs in as normal without using the custom component, and it doesn't throw the error. I built the custom component to reuse, and would like to avoid the solution not using it.
I have yet to find additional solutions that would help solve my problem.
本文标签:
版权声明:本文标题:angular - "No value accessor for form control path" Error when adding a dynamic input to form using a custom f 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745354486a2654968.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论