No Value Accessor for Form Control

I'm using Angular2-rc5, and I'm currently getting an error on my login page. I'm trying to make a form but the console throws exceptions telling me that it can't find my formcontrolls even though I create it on init. Any idea why I'm getting this error?

login component

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
import { LoginService } from './login.service';
import { User } from '../../models/user';
    
@Component({
    selector: 'login',
    providers: [LoginService],
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
    private loginForm: FormGroup; // our model driven form
    private submitted: boolean; // keep track on whether form is submitted
    private events: any[] = []; // use later to display form changes
    
    constructor(private fb: FormBuilder, private ls:LoginService){}
    ngOnInit(){
        this.loginForm = new FormGroup({
            email: new FormControl('',[<any>Validators.required]),
            password: new FormControl('', [<any>Validators.required, <any>Validators.minLength(6)]),
            rememberMe: new FormControl()
        });
    }
    save(model: User, isValid: boolean) {
        console.log("Test");
        console.log(model, isValid);
    }
    // Login in user
    login(email: any, password: any){
        this.ls.login(email, password, false); 
    }
}

Page.html

<div id="login-page">
    <div class="form-wrapper">
        <form class="login-form" [formGroup]="loginForm" novalidate (ngSubmit)="save(loginForm.value, loginForm.valid)">
            <div >
                <div class="input-field col s12 center">
                    <p class="center login-form-text">Login page</p>
                </div>
            </div>
            <div >
                <div class="input-field col s12">
                    <input id="email" type="email"> 
                    <label class="center-align" for="email" formControlName="email">Email</label>
                </div>
            </div>
            <div >
                <div class="input-field col s12">
                    <input id="password" type="password"> 
                    <label class="center" for="password" formControlName="password">Password</label>
                </div>
            </div>
            <div >
                <div class="input-field col s12 m12 l12 login-text">
                    <input id="remember-me" type="checkbox" formControlName="rememberMe">
                    <label for="remember-me">Remember me</label>
                </div>
            </div>
            <div >
                <div class="input-field col s12">
                    <ahref="index.html">Login</a>
                </div>
            </div>
            <div >
                <div >
                    <p><a href="page-register.html">Register Now!</a></p>
                </div>
                <div >
                    <p><a href="page-forgot-password.html">Forgot password ?</a></p>
                </div>
            </div>
        </form>
    </div>
</div>

Exception

EXCEPTION: Uncaught (in promise): Error: Error in ./LoginComponent class LoginComponent - inline template:13:45 caused by: No value accessor for form control with name: 'email'.....

1

13 Answers

You are adding the formControlName to the label and not the input.

You have this:

<div >
  <div class="input-field col s12">
    <input id="email" type="email"> 
    <label class="center-align" for="email" formControlName="email">Email</label>
  </div>
</div>

Try using this:

<div >
  <div class="input-field col s12">
    <input id="email" type="email" formControlName="email"> 
    <label class="center-align" for="email">Email</label>
  </div>
</div>

Update the other input fields as well.

6

For UnitTest angular 2 with angular material you have to add MatSelectModule module in imports section.

import { MatSelectModule } from '@angular/material';

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ CreateUserComponent ],
      imports : [ReactiveFormsModule,        
        MatSelectModule,
        MatAutocompleteModule,......

      ],
      providers: [.........]
    })
    .compileComponents();
  }));
2

For anyone experiencing this in angular 9+

This issue can also be experienced if you do not declare your component or import the module that declares the component.

Lets consider a situation where you intend to use ng-select but you forget to import it Angular will throw the error 'No value accessor...'

I have reproduced this error in the Below stackblitz demo.

2

If you get this issue, then either

  • the formControlName is not located on the value accessor element.
  • or you're not importing the module for that element.
3

If you must use the label for the formControl. Like the Ant Design Checkbox. It may throw this error while running tests. You can use ngDefaultControl

<label nz-checkbox formControlName="isEnabled" ngDefaultControl>
    Hello
</label>

<nz-switch nzSize="small" formControlName="mandatory" ngDefaultControl></nz-switch>

In my case I was using ionic, I was trying to unit test ion-input with jasmine karma. I was getting the no value accessor error in the karma browser while running the tests. So I just added the ngDefaultControl to the ion-input and it solved the problem.

<ion-input class="password" [(ngModel)]="user.password" name="password" 
                type="password" #pw="ngModel" required ngDefaultControl>
</ion-input>
1

In my case, I used Angular forms with contenteditable elements like div and had similar problems before.

I wrote ng-contenteditable module to resolve this problem.

OR

You need to move your formControlName="controlName" to the <mat-radio-group> wrapper instead of binding it to the individual <mat-radio-button> element (s)

You can see formControlName in label , removing this solved my problem

For me I was using primeng dropdown in angular app. The module for dropdown was not imported.

1

For me, I had the error with ionic date pickers only, I had to import the IonicModule to my lazy-loaded module

1
    constructor(
    private cdr: ChangeDetectorRef,
    @Optional() 
    @Self() public ngControl: NgControl,
    ) {

    if (ngControl) {
        ngControl.valueAccessor = this;
      }

}

In my case, add this line in custom Control (reuseable) component's constructor

if (ngControl) {
        ngControl.valueAccessor = this;
      }

In some cases you might missed to add NG_VALUE_ACCESSOR in reusable component as provider.

@Component({
    selector: 'app-reusable',
    templateUrl: './reusable.component.html',
    styleUrls: ['./reusable.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => ReusableComponent),
            multi: true,
        },
    ],
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

David Miller

David Miller

Executive Financial & Market Analyst

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.

Share this article
Twitter Facebook Pinterest