Angular 7 Reactive Forms Cannot read property 'controls' of undefined
Solution 1
Instead of the convenience method you are using, you could simply reference the field like
[ngClass]="{ 'is-invalid': submitted && loginForm.controls['username'].errors }"
It would then be a case of showing an error message if you so wish using
<div *ngIf="submitted && loginForm.controls['username'].hasError('required')" class="error-message">Username is required</div>
I am not clear on what benefit your current approach is affording you over something straight forward such as this.
Solution 2
Should be pretty easy to fix by checking loginForm
in html.
<div class="login__container" *ngIf="loginForm"> <!-- Check here -->
<div class="login__form">
<form novalidate [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="field">
<p class="control">
<input class="input" type="text" placeholder="Username" formControlName="username" [ngClass]="{ 'is-invalid': submitted && f.username.errors }">
</p>
</div>
<div class="field">
<p class="control">
<input class="input" type="password" placeholder="Password" formControlName="password" [ngClass]="{ 'is-invalid': submitted && f.password.errors }">
</p>
</div>
<div class="field">
<p class="control">
<button class="button is-success" [disabled]="!loginForm.valid">
Login
</button>
</p>
</div>
</form>
</div>
</div>
Harry Blue
Updated on June 14, 2022Comments
-
Harry Blue almost 2 years
I am using
ReactiveForms
in Angular v7.Template
<div class="login__container"> <div class="login__form"> <form novalidate [formGroup]="loginForm" (ngSubmit)="onSubmit()"> <div class="field"> <p class="control"> <input class="input" type="text" placeholder="Username" formControlName="username" [ngClass]="{ 'is-invalid': submitted && f.username.errors }"> </p> </div> <div class="field"> <p class="control"> <input class="input" type="password" placeholder="Password" formControlName="password" [ngClass]="{ 'is-invalid': submitted && f.password.errors }"> </p> </div> <div class="field"> <p class="control"> <button class="button is-success" [disabled]="!loginForm.valid"> Login </button> </p> </div> </form> </div> </div>
Component
import { Component, OnInit } from '@angular/core' import { FormBuilder, FormGroup, Validators } from '@angular/forms' @Component({ selector: 'app-login-component', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) export class LoginComponent implements OnInit { loginForm: FormGroup submitted = false constructor(private fB: FormBuilder) {} ngOnInit() { this.loginForm = this.fB.group({ username: ['', Validators.required], password: ['', Validators.required] }) } // convenience getter for easy access to form fields get f() { return this.loginForm.controls } onSubmit() { this.submitted = true // stop here if form is invalid if (this.loginForm.invalid) { return } console.log(this.loginForm.value) } }
When I go to this route, I have a console error
ERROR TypeError: Cannot read property 'controls' of undefined at Object.get [as f] (http://localhost:4200/main.js:257:35) at http://localhost:4200/vendor.js:92667:9 at Array.forEach (<anonymous>) at deepFreeze (http://localhost:4200/vendor.js:92664:33) at http://localhost:4200/vendor.js:92670:7 at Array.forEach (<anonymous>) at deepFreeze (http://localhost:4200/vendor.js:92664:33) at http://localhost:4200/vendor.js:92670:7 at Array.forEach (<anonymous>) at deepFreeze (http://localhost:4200/vendor.js:92664:33)
I cannot work out why this happening, the validation around the submit button appears to be working, so I can only assume the fields are being referenced correctly. I suspect the issue is coming from the convenience getter set within the component, however I cannot see what is wrong with this as autocomplete is providing me with the values I expect.
-
Ajay Ojha over 5 yearscheck first 'this.loginForm' is undefined or not in f method. or else you can use loginForm.controls.username.errors in the HTML.
-
shuk over 5 yearsAnother option is to pass the
formBuilder
fromngOnInit
cycle toconstructor
cycle -
Jota.Toledo over 5 yearsAs it is, Im not able to reproduce your issue stackblitz.com/edit/angular-lpstaz
-
Jota.Toledo over 5 yearsAs @OmerShukar mentioned, you could try by instantiating the form in the
constructor
-
Harry Blue over 5 yearsUsing the constructor did not help, it also doesn’t appear to follow the docs set out by Angular.
-
-
Jota.Toledo over 5 yearsThis wont make a difference