229

Here is my Angular component:

@Component( {
    selector: 'input-extra-field',
    template: `
            <div class="form-group" [formGroup]="formGroup" >
                <switch [attr.title]="field.etiquette" 
                    [attr.value]="field.valeur" [(ngModel)]="field.valeur"
                    [formControl]="fieldControl" [attr.id]="name" [attr.disabled]="disabled">
                </switch>
                <error-messages [control]="name"></error-messages>
            </div>
    `
} )

Here is my Class:

export class SwitchExtraField extends ExtraField {
    @Input() field: ExtraFormField;
    @Input() entity: { fields: Object };
    @Input() formGroup: FormGroup;

    constructor( formDir: NgForm ) {
        super( null, null, formDir );
    }

    get disabled(): string {
        if ( this.field && !!this.field.saisissable && !this.field.saisissable )     {
            return 'disabled';
        }
        return null;
    }
}

This is the error I get when compiling:

ERROR Error: No value accessor for form control with unspecified name attribute
  at _throwError (forms.es5.js:1918)
  at setUpControl (forms.es5.js:1828)
  at FormControlDirective.webpackJsonp.../../../forms/@angular/forms.es5.js.FormControlDirective.ngOnChanges (forms.es5.js:4617)

When I change the element switch to input it works, knowing that I'm using the same structure to other components and it works fine.

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
Sue
  • 2,380
  • 2
  • 10
  • 11
  • 2
    read here about `ControlValueAccessor` - [Never again be confused when implementing ControlValueAccessor in Angular forms](https://blog.angularindepth.com/never-again-be-confused-when-implementing-controlvalueaccessor-in-angular-forms-93b9eee9ee83) – Max Koretskyi Sep 26 '17 at 09:35
  • This can probably help you: https://stackoverflow.com/questions/46708080/form-control-errorerror-error-no-value-accessor-for-form-control-with-unspecif – Dinistro Oct 12 '17 at 11:51
  • 3
    Updated link for @MaxKoretskyi's '[Never again be confused when implementing ControlValueAccessor ....](https://indepth.dev/posts/1055/never-again-be-confused-when-implementing-controlvalueaccessor-in-angular-forms) – mcalex Oct 14 '21 at 03:38
  • I got this error because I had a custom component with an `@Input` property named `formControl` for a little different usage. I feel kind of stupid right now – O-9 Nov 30 '22 at 07:48

31 Answers31

308

I fixed this error by adding the name="fieldName" ngDefaultControl attributes to the element that carries the [(ngModel)] attribute.

isherwood
  • 58,414
  • 16
  • 114
  • 157
Pierre-Alexis Ciavaldini
  • 3,369
  • 1
  • 14
  • 16
  • 53
    Some additional explanation would make this a better answer. Where did you find documentation of `ngDefaultControl`, for example? – isherwood Jan 23 '18 at 16:06
  • 48
    I think `name="fieldname"` is not necessary, but `ngDefaultControl` cures the problem. – michaeak Feb 19 '20 at 08:19
  • 12
    More explanation is here. https://stackoverflow.com/questions/46465891/what-is-ngdefaultcontrol-in-angular/46465959 – I'm nidhin Aug 08 '20 at 07:03
  • Adding "ngDefaultControl" (on the attribute with *ngFor directive) solved my similar problem. – Davidson Lima Sep 09 '20 at 19:45
  • 7
    for me, I fixed this by importing the module package for an element used in form group (e.g. AngularEditorModule) to recognize the control in the template and ngDefaultControl will able to access it. I discovered it while I'm doing unit test. – aj go Nov 21 '20 at 03:03
  • 1
    Just adding ngDefaultControl fixed this error for me – Chris Snowden Jan 04 '21 at 12:06
  • this fixed my error using a custom input element, just passed it like this: – Matheus Ribeiro Feb 25 '21 at 19:20
  • @michaeak For me it seems to be just the opposite. I just needed name="fieldname". – Evan Sevy Mar 19 '21 at 03:27
  • got this during the writing of Jest unit tests. to fix it I only needed to add all the correct imports for the fields like MatCheckboxModule, MatInputModule, etc – Liviu Trifoi Jan 21 '22 at 12:13
230

I had the same problem and the issue was that my child component had an @input named formControl.

So I just needed to change from:

<my-component [formControl]="formControl"><my-component/>

to:

<my-component [control]="control"><my-component/>

ts:

@Input()
control:FormControl;
Ahmad Baktash Hayeri
  • 5,802
  • 4
  • 30
  • 43
Eduardo Vargas
  • 8,752
  • 2
  • 20
  • 27
  • 3
    Works with Angular 10, as said in a previous comment, it's really tough to track down this one, however, afterwards, it makes sense that "formControl" shouldn't be used as an component @Input property name because of a potential namespace conflict, another naming solution could be to rename the field _formControl which is fed by a FormControl instance. – Thomas Sep 03 '20 at 12:28
  • This is the right solution for me, thanks. – André Machado Apr 06 '22 at 10:40
  • Thank you so much. this problem was so annoying and this fix worked perfectly. – vikingsteve Jul 13 '23 at 07:40
81

I also received this error while writing a custom form control component in Angular 7. However, none of the answers are applicable to Angular 7.

In my case, the following needed to be add to the @Component decorator:

  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyCustomComponent),  // replace name as appropriate
      multi: true
    }
  ]

This is a case of "I don't know why it works, but it does." Chalk it up to poor design/implementation on the part of Angular.

theMayer
  • 15,456
  • 7
  • 58
  • 90
  • 14
    This snippet tells Angular's dependency injection layer that your class should be returned when other classes (ie the formControlName directive) ask it for the token NG_VALUE_ACCESSOR. Without it, angular would have no way of knowing that your class is a custom form control (all info about interfaces etc is stripped out during transpilation) – Max Mumford May 05 '20 at 16:07
43

I also had the same error , angular 7

 <button (click)="Addcity(city.name)" [(ngModel)]="city.name"  class="dropdown-item fontstyle"
     *ngFor="let city of Cities; let i = index">
      {{city.name}}
 </button>

I just added ngDefaultControl

   <button (click)="Addcity(city.name)" [(ngModel)]="city.name"  ngDefaultControl class="dropdown-item fontstyle"
 *ngFor="let city of Cities; let i = index">
  {{city.name}}

Nadeem Qasmi
  • 2,217
  • 22
  • 16
32

I was facing this error while running Karma Unit Test cases Adding MatSelectModule in the imports fixes the issue

imports: [
        HttpClientTestingModule,
        FormsModule,
        MatTableModule,
        MatSelectModule,
        NoopAnimationsModule
      ],
Dan Patil
  • 771
  • 6
  • 15
  • 2
    Only if you have "Angular Material" installed, otherwise you don't need this. – Mikefox2k May 18 '20 at 07:23
  • 2
    I'd like to add that this applies to any "input" element from Angular Material. For example, I had a Slide Toggle element with a Form Control and it gave me the "no value accessor" error when running Karma tests. Turns out, I had to add the MatSlideToggleModule import to my "spec.ts" class to have it recognize the input. – Gabriel Lovetro Nov 24 '21 at 13:27
  • My issue was very similar to this but was related to a different 3rd party module (UiSwitchModule). – Ben Thomson Oct 31 '22 at 02:57
  • Same issue but different modules. I had to add `MatAutocompleteModule` and `MatInputModule`. – nedstark179 Apr 04 '23 at 11:17
19

I was getting this error message in my Unit tests with Jasmine. I added ngDefaultControl attribute to the custom element(in my case it was an angular material slide toggle) and this resolves the error.

<mat-slide-toggle formControlName="extraCheese">
  Extra Cheese
</mat-slide-toggle>

Change the above element to include ngDefaultControl atttribute

<mat-slide-toggle ngDefaultControl formControlName="extraCheese">
 Extra Cheese
</mat-slide-toggle>
Sudharshan
  • 3,634
  • 2
  • 27
  • 27
  • This helped me, my app was slow and showing that error and adding this to my navbar fixed it. – MADMVX Oct 25 '22 at 05:11
  • This fixed it for me. In my case, I had a sub-form formGroup inside a formControl element in the angular template. Adding `ngDefaultControl` to the top level form fixed it. – RedRain Jan 04 '23 at 02:59
14

I also received this error when I named one of my component inputs 'formControl'. Probably it's reserved for something else. If you want to pass FormControl object between components, use it like that:

@Input() control: FormControl;

not like this:

@Input() formControl: FormControl;

Weird - but working :)

Pawel
  • 159
  • 1
  • 8
  • that is because `formControl` is Angular's default directive for binding form controls to an input field – sschmid Feb 08 '21 at 08:43
14

In my case I forgot to add providers: [INPUT_VALUE_ACCESSOR] to my custom component

I had INPUT_VALUE_ACCESSOR created as:

export const INPUT_VALUE_ACCESSOR = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TextEditorComponent),
  multi: true,
};
Jobu
  • 181
  • 1
  • 5
14

This happens when you use ngModel or formControl on an element which cannot have a value like a <div> element.

Problem occurs when ngModel or formControl is used like this:

<div [(ngModel)]="myModel"> <--- wrong place
    <input type="text" />
</div>

Solution:

<div>
    <input type="text" [(ngModel)]="myModel" /> <--- correct place
</div>

Source: https://github.com/angular/angular/issues/43821#issuecomment-992305494

Sameer Basil
  • 366
  • 5
  • 11
10

In my case the problem was that i created an @Input variable with the reserved name formControl.

Dharman
  • 30,962
  • 25
  • 85
  • 135
moolsbytheway
  • 1,152
  • 13
  • 20
9

I had this same error- I accidentally binded [(ngModel)] to my mat-form-field instead of the input element.

Chris Fremgen
  • 4,649
  • 1
  • 26
  • 26
8

In my case i used directive, but hadn't imported it in my module.ts file. Import fixed it.

Andris
  • 3,895
  • 2
  • 24
  • 27
7

This is kind of stupid, but I got this error message by accidentally using [formControl] instead of [formGroup]. See here:

WRONG

@Component({
  selector: 'app-application-purpose',
  template: `
    <div [formControl]="formGroup"> <!-- '[formControl]' IS THE WRONG ATTRIBUTE -->
      <input formControlName="formGroupProperty" />
    </div>
  `
})
export class MyComponent implements OnInit {
  formGroup: FormGroup

  constructor(
    private formBuilder: FormBuilder
  ) { }

  ngOnInit() {
    this.formGroup = this.formBuilder.group({
      formGroupProperty: ''
    })
  }
}

RIGHT

@Component({
  selector: 'app-application-purpose',
  template: `
    <div [formGroup]="formGroup"> <!-- '[formGroup]' IS THE RIGHT ATTRIBUTE -->
      <input formControlName="formGroupProperty" />
    </div>
  `
})
export class MyComponent implements OnInit {
  formGroup: FormGroup

  constructor(
    private formBuilder: FormBuilder
  ) { }

  ngOnInit() {
    this.formGroup = this.formBuilder.group({
      formGroupProperty: ''
    })
  }
}
Trevor
  • 13,085
  • 13
  • 76
  • 99
6

In my case, it was happening in my shared module and I had to add the following into @NgModule:

...
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    IonicModule
  ],
...
Pei
  • 11,452
  • 5
  • 41
  • 45
  • This was happening for me with the change to the `ng-zorro` angular ocmponents. they changed the way that its components are imported. I had just missed the checkbox component. – Qpirate Jan 15 '21 at 11:46
5

In my case, I had inserted [(ngModel)] on label rather than input. There is also a caveat, I tried running after correctly the above error in the specified line but the error wouldn't go. If there are other places where you have committed the same mistake, it still throws you the same error at the same line

  • 1
    This is a good answer. Some components (select, radio, etc) you can slip up and stick the ngModel in the wrong place like this. The error message doesn't help much. – AndrewBenjamin Dec 20 '19 at 04:04
5

This error also occurs if you try to add ngModel to the non-input elements like <option> HTML tags. Make sure you add ngModel only to the <input> tags. In my case, I have added a ngModel to the <ion-select-option> instead of <ion-select>.

Sandy
  • 171
  • 2
  • 9
5

I was using a formControl in a mat-select like this:

<mat-select [formControl]="control">
 ...
</mat-select>

and I realized that MatSelectModule was not imported in the spec file, that solved the issue.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Luis Lopez
  • 51
  • 1
  • 1
4

If this helps somebody, I was getting this error cause I had the ngModel inside the option tag on a select.

By mistake (mine), I had this:

<select class="form-control">
    <option *ngFor="let mystate of data.states" value="{{mystate.stateAbbreviation}}" [(ngModel)]="dependent.state">{{mystate.stateName}}</option>
</select>

Instead of this:

<select class="form-control" [(ngModel)]="dependent.state">
    <option *ngFor="let mystate of data.states" value="{{mystate.stateAbbreviation}}" >{{mystate.stateName}}</option>
</select>
Danielle
  • 1,386
  • 8
  • 22
3

It is looks like "formControl" is reserved name by Angular Forms, when I used this name as an input to my component, I got unexpected behavior with my actual from control. If you ask me, this is an Angular bug. Just replace your input name to something else like "frmCtrl" or whatever, and it will work.

Hagay Levy
  • 61
  • 1
  • 2
  • 5
2

I had this same error, I had a input field named control in my custom Form Component but was accidentally passing control in input named formControl. Hope no one faces that issue.

Nikhil Arora
  • 141
  • 4
2

In my case it was as daft as having registered the new component for DI in my app.module.ts declarations but not in exports.

Wikooo
  • 29
  • 5
  • Yeah, similar here. I just forgot to import my library that had my custom control in it. It took me a while to discover because it used to give the long-winded error "If this is not an Angular component then...". If I had seen that I would have known immediately what it was. Alas. – crowmagnumb Jul 01 '21 at 19:41
2

I also created a custom control.
The following resolved this issue:

constructor(
  @Optional() @Self()
  readonly ngControl: NgControl,
) {
  this.ngControl.valueAccessor = this;
}
Stephen Paul
  • 37,253
  • 15
  • 92
  • 74
1

I had the same error, but in my case apparently it was a synchronization issue, at the moment of render the components html.

I followed some of the solutions proposed on this page but any of them worked for me, at least not completely.

What did actually solve my error was to write the below code snippet inside the father html tag of the elements .

I was binding to the variable.

Code:

    *ngIf="variable-name"

The error was caused, apparently by the project trying to render the page, apparently at the moment of evaluating the variable, the project just could no find its value. With the above code snippet you make sure that before rendering the page you ask if the variable has being initialized.

This is my component.ts code:

import { Component, OnInit } from '@angular/core';
import { InvitationService } from 'src/app/service/invitation.service';
import { BusinessService } from 'src/app/service/business.service';
import { Invitation } from 'src/app/_models/invitation';
import { forEach } from '@angular/router/src/utils/collection';

@Component({
  selector: 'app-invitation-details',
  templateUrl: './invitation-details.component.html',
  styleUrls: ['./invitation-details.component.scss']
})
export class InvitationDetailsComponent implements OnInit {
  invitationsList: any;
  currentInvitation: any;
  business: any;
  invitationId: number;
  invitation: Invitation;

  constructor(private InvitationService: InvitationService, private BusinessService: 
BusinessService) { 
this.invitationId = 1; //prueba temporal con invitacion 1
this.getInvitations();
this.getInvitationById(this.invitationId);
  }

   ngOnInit() {

  }

  getInvitations() {
    this.InvitationService.getAllInvitation().subscribe(result => {
      this.invitationsList = result;
      console.log(result);
    }, error => {
      console.log(JSON.stringify(error));
    });
  }

  getInvitationById(invitationId:number){
    this.InvitationService.getInvitationById(invitationId).subscribe(result => {
      this.currentInvitation = result;
      console.log(result);
      //this.business=this.currentInvitation['business'];
       //console.log(this.currentInvitation['business']); 
     }, error => {
     console.log(JSON.stringify(error));
    });
  }
      ...

Here is my html markup:

<div class="container-fluid mt--7">
  <div class="row">
    <div class="container col-xl-10 col-lg-8">
      <div class="card card-stats ">
        <div class="card-body container-fluid form-check-inline" 
         *ngIf="currentInvitation">
          <div class="col-4">
             ...

I hope this can be helpful.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
NUKE
  • 71
  • 1
  • 6
  • this link has a similar issue:, https://stackoverflow.com/q/49409674/8992452 perhaps it can help with the problem – NUKE Aug 31 '19 at 02:08
1

Have you tried moving your [(ngModel)] to the div instead of the switch in your HTML? I had the same error appear in my code and it was because I bound the model to a <mat-option> instead of a <mat-select>. Though I am not using form control.

mneumann
  • 713
  • 2
  • 9
  • 42
1

In my case it was a component.member which was not existing e.g.

[formControl]="personId"

Adding it to the class declaration fixed it

this.personId = new FormControl(...)
Stefan Michev
  • 4,795
  • 3
  • 35
  • 30
1

I was facing this issue while running unit tests. To fix I added the MatSlideToggleModule to the imports in my spec.ts file.

Jadamae77
  • 828
  • 7
  • 13
1

I had the same error just need to import forms module in module.ts

import { FormsModule } from '@angular/forms';
    
@NgModule({
    imports: [FormsModule]
)}
Blastfurnace
  • 18,411
  • 56
  • 55
  • 70
0

In my case, the error was triggered by duplicating an import of a component in the module.

Aleks Grunwald
  • 315
  • 3
  • 12
0

#Background

  • NativeScript 6.0

In my case, the error was triggered by changing element tag from to by fault. Inside <TextView an [(ngModel)]="name". was defined.

After removing [(ngModel)]="name" error was gone.

Chris S
  • 11
  • 1
0

I'm facing the same problem when I try to integrate angular editor

I resolve that by adding [ngModelOptions]="{standalone: true}" to my tag.

<angular-editor [ngModelOptions]="{standalone: true}" [(ngModel)]="htmlContent" [config]="config"></angular-editor>

I hope it's the quickest solution reference

Neel Rathod
  • 2,013
  • 12
  • 28
-1

in my case, I had a <TEXTAREA> tag from old html while converting to angular. Had to change to <textarea>.

Feng Zhang
  • 1,698
  • 1
  • 17
  • 20