Sue
Sue

Reputation: 2750

ERROR Error: No value accessor for form control with unspecified name attribute on switch

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.

Upvotes: 266

Views: 524666

Answers (30)

Simon_Weaver
Simon_Weaver

Reputation: 146180

Check for basic typos in the control you're using.

I'm using signals, where item.selected is a Signal<boolean> and was getting the same error on the following code:

<mat-checkout [(ngModel)]="item.selected">{{ item.desc }}</mat-checkout>

Spot the problem?... I'd put mat-checkout instead of mat-checkbox. No compile errors.

Upvotes: 0

Abdullah Tahan
Abdullah Tahan

Reputation: 2129

I got this issue when i had a child component that is implements ControlValueAccessor i had to add on top of my child component with NG_VALUE_ACCESSOR

@Component({
    selector: 'app-example',
    templateUrl: './app-example-sub-form.component.html',
    styleUrls: ['./app-example-sub-form.component.scss'],
    changeDetection: ChangeDetectionStrategy.OnPush,
    providers: [
        {
            // should add these
            provide: [NG_VALUE_ACCESSOR],
            useExisting: forwardRef(() => ExampleComponent),
            multi: true,
        },
    ],
})

Upvotes: 0

Twinshu Parmar
Twinshu Parmar

Reputation: 61

check your component is standalone or not.

if it is has standalone:true, you have to import input module.

I was using mat-slide-toggle from angular material, and I was getting same error.

Add in your imports like this: imports: [CommonModule, FormsModule, ReactiveFormsModule, SharedModule, MatSlideToggleModule]

Upvotes: 3

Tam&#225;s Szab&#243;
Tam&#225;s Szab&#243;

Reputation: 81

I fixed it by wrapping the form field in a <form> tag

Upvotes: 0

ranbuch
ranbuch

Reputation: 1642

In my case, after updating Angular Material I've added an input with the matSliderThumb attribute to each <mat-slider> element as follows:

Before:

<mat-slider>
</mat-slider>

After:

<mat-slider>
  <input matSliderThumb>
</mat-slider>

But this wasn't enough on cases where I had [(ngModel)] or formControlName attributes. I had to move those attributes as well:

Before:

<mat-slider [(ngModel)]="myVar">
  <input matSliderThumb>
</mat-slider>

After:

<mat-slider>
  <input matSliderThumb [(ngModel)]="myVar">
</mat-slider>

Please see documentation here to understand which attributes to move from the element to the child input.

Upvotes: 1

Stephen Paul
Stephen Paul

Reputation: 39035

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

constructor(
  @Optional() @Self()
  readonly ngControl: NgControl,
) {
  this.ngControl.valueAccessor = this;
}

Upvotes: 1

Sameer Basil
Sameer Basil

Reputation: 496

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

Upvotes: 24

Neel Rathod
Neel Rathod

Reputation: 2111

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

Upvotes: 0

user19074538
user19074538

Reputation: 21

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

import { FormsModule } from '@angular/forms';
    
@NgModule({
    imports: [FormsModule]
)}

Upvotes: 2

Hagay Levy
Hagay Levy

Reputation: 101

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.

Upvotes: 7

Danielle
Danielle

Reputation: 1496

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>

Upvotes: 4

Jadamae77
Jadamae77

Reputation: 928

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

Upvotes: 2

Luis Lopez
Luis Lopez

Reputation: 71

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.

Upvotes: 6

Pei
Pei

Reputation: 11643

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

...
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    IonicModule
  ],
...

Upvotes: 8

moolsbytheway
moolsbytheway

Reputation: 1292

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

Upvotes: 13

Jobu
Jobu

Reputation: 311

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,
};

Upvotes: 16

Sandy
Sandy

Reputation: 301

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

Upvotes: 5

Pawel
Pawel

Reputation: 189

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 :)

Upvotes: 17

Chris S
Chris S

Reputation: 31

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

Upvotes: 0

Aleks Grunwald
Aleks Grunwald

Reputation: 385

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

Upvotes: 0

Wikooo
Wikooo

Reputation: 29

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.

Upvotes: 2

Feng Zhang
Feng Zhang

Reputation: 1960

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

Upvotes: -1

Trevor
Trevor

Reputation: 13457

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: ''
    })
  }
}

Upvotes: 8

Sudharshan
Sudharshan

Reputation: 3823

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>

Upvotes: 23

Stefan Michev
Stefan Michev

Reputation: 5093

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(...)

Upvotes: 1

mneumann
mneumann

Reputation: 786

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.

Upvotes: 1

Dan Patil
Dan Patil

Reputation: 801

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
      ],

Upvotes: 36

NUKE
NUKE

Reputation: 79

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.

Upvotes: 1

Nikhil Arora
Nikhil Arora

Reputation: 141

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.

Upvotes: 2

Eduardo Vargas
Eduardo Vargas

Reputation: 9402

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;

Upvotes: 272

Related Questions