149

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'.....

PaulBunion
  • 346
  • 2
  • 18
AJ_
  • 3,787
  • 10
  • 47
  • 82

13 Answers13

202

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.

Usman Maqbool
  • 3,351
  • 10
  • 31
  • 48
ppovoski
  • 4,553
  • 5
  • 22
  • 28
  • 3
    The same issue to me because I applied formControlName for a span tag. Thank you! – Anh Hoang Mar 15 '17 at 08:10
  • 4
    I even had this issue with a custom component that had a `@Input formControl`. In one place the formControl was correctly passed to my component in another one the above error occurred. I ended up renaming the formControl input to something distinct. Without this answer I would've never found this :/ – Pieter De Bie Dec 23 '18 at 08:02
  • 2
    A thumbs up from me too for this solution - I'm using a `` element and had the `formControlName` applied to that (didn't work). Moving it to the contained `` element resolved the issue perfectly! – Ade Feb 12 '19 at 22:44
  • I was using ngModel in the option tag, so I moved it to the select tag and it worked. Thank you! – José Ripoll Jan 13 '20 at 15:59
  • 2
    I had the same issue (in a test and the actual component separate times) because I was using a form control name on a custom element and I forgot to import the module for that element, which prevented form control from proper binding. – Rov Feb 11 '20 at 21:25
  • How to apply this solution in case of **Material Checkbox**? – meDeepakJain Oct 07 '20 at 11:24
86

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();
  }));
Mansur Haider
  • 1,157
  • 9
  • 4
66

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.

Owen Kelvin
  • 14,054
  • 10
  • 41
  • 74
  • 2
    A better answer would be with a solved demo, instead of recreating the same error – Lenzman Jun 02 '21 at 16:37
  • 7
    @Lenzman I think the solution is quite clear. This answer is to assist anyone who might be facing this issue because of not importing a particular component. If you believe this is not a solution you were looking for or expect others to find here on SO, you are welcomed to provide your solution – Owen Kelvin Jun 02 '21 at 16:46
  • 1
    @OwenKelvin, the solution is not clear to me. Import exactly what exactly where? Thanks. – Adam M. Costello Sep 21 '22 at 00:22
29

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.
Rstar37
  • 454
  • 5
  • 6
14

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>
Phat Tran
  • 3,404
  • 1
  • 19
  • 22
8

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>
Shadab Umer
  • 173
  • 3
  • 12
  • I have two different projects on the same framework versions, one needed the ngDefaultControl, the other worked fine without it. Weird. – ScottN Nov 09 '21 at 01:56
  • I did a refactor and now my ionic form require the ngDefaultControl. Not sure why – Quethzel Diaz Oct 17 '22 at 04:31
8

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,
        },
    ],
})
SKL
  • 1,243
  • 4
  • 32
  • 53
7

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)

Hlawuleka MAS
  • 550
  • 5
  • 11
5

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

Adeel Shekhani
  • 995
  • 1
  • 11
  • 16
4

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.

L1ghtk3ira
  • 3,021
  • 6
  • 31
  • 70
ktretyak
  • 27,251
  • 11
  • 40
  • 63
4

enter image description here

enter image description here

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

kuldeep chopra
  • 652
  • 9
  • 9
2
    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;
      }
Kashif Faraz
  • 321
  • 6
  • 19
1

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

et3rnal
  • 322
  • 4
  • 17