Solving The Error “No Value Accessor For Form Control With Name”

Solving The Error “No Value Accessor For Form Control With Name”

The error “No value accessor for form control with name” occurs when you are programming in the Angular framework. It’s not an impossible exception. With just a few lines of code, you can fix this error.

The causes of the “No value accessor for form control with name” error

There are two common reasons cause this problem.

1. When we add the formControlName attribute into the element like the label.

<form [formGroup]="addressForm">
  <label for="fname" formControlName="fname">Full name</label>
  <input id="fname" type="text" />
  <label for="age" formControlName="age">Age</label>
  <input id="age" type="number" />
</form>

With the above code sample, we get an error like this:

ERROR Error: No value accessor for form control with name: 'fname'
ERROR Error: No value accessor for form control with name: 'age'

2. We miss the providers of @Component while we use Control Value Accessor.

@Component({
  selector: 'my-input',
  templateUrl: './my-input.component.html',
  styleUrls: ['./my-input.component.scss'],
 
  // Missing providers HERE
  
})

The above code sample makes an error like this:

ERROR Error: No value accessor for form control with name: 'myFormControl'

Solutions for this error

Case 1: Place the formControlName on an HTML element supported by Angular

You should use formControlName = “fname” and formControlName = “age” on an input tag, not on a label tag.

Like this:

<form [formGroup]="addressForm">
  <label for="fname">Full name</label>
  <input id="fname" type="text" formControlName="fname" />
  <label for="age">Age</label>
  <input id="age" type="number" formControlName="age" />
</form>

Output:

Case 2: Create a provider of the ControlValueAccessor

Implement interface

So, to solve this problem, we have to implement the ControlValueAccessor Interface by implementing three functions of ControlValueAccessor:

  • writeValue() (to write to the view when programmatic changes from model to view are requested).
  • registerOnChange() (creates a function called at the time the control’s value changes in view).
  • registerOnTouched() (creates a function called at the time the component gets a touch or blur event).

Create a provider

Let Angular know that your component is a ControlValueAccessor. First, you have to register a provider.

The provider should contain NG_VALUE_ACCESSOR. You’ll also need a forwardRef() in this provider.

For instance, if your component is named MyComponent, you should create a provider containing the provide is NG_VALUE_ACCESSOR and pass it into the component:

providers: [
  { 
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => MyComponent),
    multi: true,
  }
]

Put it together

After implementing the ControlValueAccessor and registering a provider, the source code looks like this:

@Component({
  selector: 'my-input',
  templateUrl: './my-input.component.html',
  styleUrls: ['./my-input.component.scss'],
 
  //Added Providers
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true,
    },
  ],
})
 
export class CustomInputComponent implements ControlValueAccessor {
  onChange: any = () => {};
  onTouch: any = () => {};
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouch = fn;
  }
  input: string;
  writeValue(input: string) {
    this.input = input;
  }
}

Result

You can use the formControlName attribute properly, and your form will work as expected without error.

<h1>My Form</h1>
<form [formGroup]="form">
  	<my-input formControlName="myFormControl">
</my-input>
</form>

Summary

We have shown you two solutions to fix the “No value accessor for form control with name” error. So just choose the solution that best suits your case. And then you can fix it quickly.

Have a great day.

Maybe you are interested:

Leave a Reply

Your email address will not be published. Required fields are marked *