Property 'fName' comes from an index signature, so it must be accessed with ['fName']

Viewed 62973

These are my files. I am getting this error can someone help me.

Error: src/app/app.component.html:5:123 - error TS4111: Property 'fName' comes from an index signature, so it must be accessed with ['fName'].
        <input id="name" type="text" formControlName="fName" class="form-control" [ngClass]="{'is-invalid':submitted && f.fName.errors}"/>

component.html

    <form [formGroup]="surveyForm" (ngSubmit)="onSubmit()">
      <div>
        <label>Name:</label>
        <input id="name" type="text" formControlName="fName" class="form-control" [ngClass]="{'is-invalid':submitted && f.fName.errors}"/>
        <div *ngIf="submitted && f.fName.errors" class="form-control">first name is required</div>
      </div>
    </form>

component.ts


    import { Component, OnInit } from '@angular/core';
    import { FormControl, FormBuilder, FormGroup, Validators} from '@angular/forms';
    @Component({
    selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
      })
      export class AppComponent implements OnInit{
        surveyForm!: FormGroup;
        submitted= false;

     constructor(private  formBuilder: FormBuilder){}

     ngOnInit(){
     this.surveyForm = this.formBuilder.group({
       fName: ['',Validators.required]
      });
    }  
    //name = new FormControl('');
    get f() { return this.surveyForm.controls; }

     onSubmit() {
     this.submitted = true;

    // stop here if form is invalid
    if (this.surveyForm.invalid) {
        return;
    }

    // display form values on success
    alert('SUCCESS!! :-)\n\n' + JSON.stringify(this.surveyForm.value, null, 4));
    }

     onReset() {
    this.submitted = false;
    this.surveyForm.reset();
    }}

module.ts


    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { ReactiveFormsModule } from '@angular/forms';
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    import { FormsModule } from '@angular/forms';
    //import { FormBuilder } from '@angular/forms';

    @NgModule({
     declarations: [
       AppComponent
     ],
    imports: [
     BrowserModule,
     AppRoutingModule,
     FormsModule,
     ReactiveFormsModule,
     //FormBuilder
     ],
    //declarations: [AppComponent],
      providers: [
     //FormBuilder
     ],
     bootstrap: [AppComponent]
     })
     export class AppModule { }
10 Answers

In my opinion, this is a completely unnecessary feature in TypeScript. To disable it, you need to change the file tsconfig.json:

"compilerOptions": {
// ...
  "noPropertyAccessFromIndexSignature": false,
// ...
}

let clarify what is the issue. We are talking about a template-driven form validation. You need to validate something, let's say to ensure that a field is required (call it firstName). Note that from Angular v13, it changed a bit from an old code like this:

<div *ngIf="firstName.errors?.required">First Name is required</div>

to this

<div *ngIf="firstName.errors?.['required']">First Name is required</div>

As a reminder, the '?' is to ensure that the errors object is not null.

More details are here: https://angular.io/guide/form-validation

Angular 13 Form Validation with Reactive Forms Example

add form() getter for easy access to form fields in *.component.ts file

//convenience getter for easy access to form fields
get form(): { [key: string]: AbstractControl; }
{
    return this.signInForm.controls;
}

Access to email field errors example

form['email'].errors

form['email'].errors['required']

form['email'].errors['email']

signInForm HTML example

<form [formGroup]="signInForm" (ngSubmit)="onSubmit()">

    <div class="form-group">
        <label for="email">Email</label>
        <input type="email" formControlName="email" class="form-control"
            [ngClass]="{ 'is-invalid': submitted && form['email'].errors }" />
        <div *ngIf="submitted && form['email'].errors" class="invalid-feedback">
            <div *ngIf="form['email'].errors['required']">
                Field is required
            </div>
            <div *ngIf="form['email'].errors['email']">
                Email format is invalid
            </div>
        </div>
    </div>

    <div class="form-group mt-3">
        <label for="password">Password</label>
        <input type="password" formControlName="password" class="form-control"
            [ngClass]="{ 'is-invalid': submitted && form['password'].errors }" />
        <div *ngIf="submitted && form['password'].errors" class="invalid-feedback">
            <div *ngIf="form['password'].errors['required']">
                Password is required
            </div>
        </div>
    </div>

    <div class="mt-3 d-flex justify-content-between">
        <button type="submit" [disabled]="isLoading" mat-flat-button color="primary">
            <span *ngIf="isLoading" class="spinner-border spinner-border-sm mr-1"></span>
            Sign in
        </button>
    </div>

</form>

Answer:

<span *ngIf="username?.errors?.['required']">Name is required</span>
<span *ngIf="username?.errors?.['minlength']">
    Name must be 3 
charchters</span>

Here is the answer to the question Error: src/app/reactive-signup/reactive-signup.component.html:16:52 - error TS4111: Property 'required' comes from an index signature, so it must be accessed with ['required'].

<span *ngIf="username?.errors.required">
    Name is required
</span>

In angular 14.0.4, it only worked for me with

<div *ngIf="user?.errors?.['required'] ">First Name is required</div>

Angular 13 Form Validation with Reactive Forms and Form Builder, I had found the solution in Angular document, they have some different with Angular 12, you can try this:

<div *ngIf="submitted && surveyForm.get('fName')?.valid" class="form-control">first name is required</div>

worked in my case.

<div *ngIf="firstName.errors?.required">
        <b>First Name is required</b>
      </div>

Please use f['fName'].errors instead of f.fName.errors.

<input id="name" type="text" formControlName="fName" class="form-control" [ngClass]="{'is-invalid':submitted && f['fName'].errors}"/>

Check on this example

file.ts

formBuilderInit() {
        this.form = this.formBuilder.group({
            first_name: [null, Validators.required],
            middle_name: [],
            last_name: [null, Validators.required],
            email: [],
            tel: [null, [Validators.required, Validators.pattern('^[0-9]{12}$')]],
        });
    }

    // convenience getter for easy access to form fields
    get f(): { [key: string]: AbstractControl; } {
        return this.form.controls;
    }

file.html

<mat-label for="tel">Telephone</mat-label>
    <mat-form-field>
       <input
          type="number"
          matInput
          formControlName="tel"
          class="form-control"
          placeholder="Ex: 250722353933"
          [ngClass]="{ 'is-invalid': submitted && f['tel'].errors }"
       />
       </mat-form-field>
       <div *ngIf="submitted && f['tel'].errors" class="invalid-feedback">
        <div *ngIf="f['tel'].errors['required']">Telephone Number is required</div>
            <div *ngIf="f['tel'].errors['pattern']">
               Phone number must be at least 12 digit numbers
            </div>
       </div>

Bro just use f['fullName'].errors[required] instead of f.fName.errors.required

Q:Property 'fullname' comes from an index signature, so it must be accessed with ['fullname']

Related