Reputation: 57
Can someone explain what this actually means? I am new to Angular and currently using Angular 8 and this appears on my console.
ERROR TypeError: Cannot read property 'invalid' of undefined
at Object.eval [as updateDirectives] (RegisterComponent.html:10)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:45259)
at checkAndUpdateView (core.js:44271)
at callViewAction (core.js:44637)
at execComponentViewsAction (core.js:44565)
at checkAndUpdateView (core.js:44278)
at callViewAction (core.js:44637)
at execEmbeddedViewsAction (core.js:44594)
at checkAndUpdateView (core.js:44272)
at callViewAction (core.js:44637)
Here's my sourcode which implies the page that have the errors
register.component.ts
import { authTkn } from './../shared/model/loginDetails';
import { MahasiswaApiService } from './../shared/services/mahasiswa-api.service';
import { Component, OnInit } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { first } from 'rxjs/operators';
import * as CryptoJS from 'crypto-js';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss']
})
export class RegisterComponent implements OnInit {
public authTkn: authTkn = null;
registerForm = this.fb.group({
user_name: ['', Validators.required],
fullname: ['', Validators.required],
telepon: ['', Validators.required],
email: ['', Validators.required],
alamat: ['', Validators.required],
birthdate: ['', Validators.required],
foto_profil: ['', Validators.required],
password: ['', Validators.required],
});
constructor(private mahasiswaApi: MahasiswaApiService, private route: Router, private fb: FormBuilder) { }
ngOnInit() {
}
onSubmit() {
this.registerForm.controls.password.patchValue(
CryptoJS.SHA512(this.registerForm.value.password).toString()
);
console.log(this.registerForm.value);
this.mahasiswaApi.postUserRegister(this.registerForm.value).subscribe(
res => {
console.log(res);
this.authTkn = res;
console.log(this.authTkn);
localStorage.setItem('token', this.authTkn.token);
this.mahasiswaApi.getCurrentToken();
this.route.navigate(['/home']);
alert(this.authTkn.info);
},
error => {
console.log(error);
alert(error.error.message);
}
);
}
}
register.component.html
<div class="login-form">
<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
<h2 class="text-center"> Register </h2>
<!-- Register Username -->
<div class="form-group">
<label for="user_name"> Username </label>
<input type="text" class="form-control" name="Username" formControlName="user_name" placeholder="text">
<div class="alert alert-danger" *ngIf="user_name.invalid && user_name.dirty" @myInsertRemoveTrigger>Username Must Be filled</div>
</div>
<!-- Register Nama Lengkap -->
<div class="form-group">
<label for="nama lengkap"> Nama Lengkap </label>
<input type="text" class="form-control" name="Nama Lengkap" formControlName="fullname" placeholder="text">
<div class="alert alert-danger" *ngIf="fullname.invalid && fullname.dirty" @myInsertRemoveTrigger> Please fill your complete name here</div>
</div>
<!-- Register Nomor Telepon -->
<div class="form-group">
<label for="nomor_telepon"> Nomor Telepon </label>
<input type="text" class="form-control" name="Nomor Telepon" formControlName="telepon" placeholder="text">
</div>
<!-- Register Email -->
<div class="form-group">
<label for="email"> Email </label>
<input type="email" class="form-control" name="Email" formControlName="email" placeholder="email">
</div>
<!-- Register Tanggal Lahir -->
<div class="form-group">
<label for="Tanggal_lahir"> Tanggal Lahir </label>
<input type="date" class="form-control" name="Tanggal Lahir" formControlName="birthdate" placeholder="date">
</div>
<!-- Register Foto -->
<div class="form-group">
<label for="Foto_Profil"> Foto Profil </label>
<input type="file" class="form-control" name="Foto Profil" formControlName="foto_profil" placeholder="file">
</div>
<!-- Register Password -->
<div class="form-group">
<label for="Password"> Password </label>
<input type="password" class="form-control" name="Password" formControlName="password" placeholder="password">
<div class="alert alert-danger" *ngIf="password.invalid && password.dirty" @myInsertRemoveTrigger>Password Must Be filled</div>
</div>
<!-- Button shit -->
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block" [disabled]="!registerForm.valid"> Register </button>
</div>
<div class="clearfix">
<label class="pull-left checkbox-inline"><input type="checkbox" formControlName="remember_me"> Remember me</label>
</div>
</form>
</div>
Maybe I had some variable definition problem, but I did actually define arrays of used variables for my form at the first part of my ts. Maybe I did lost something, what is that?
Upvotes: 2
Views: 9394
Reputation: 800
Add #fullname = "ngModel"
to the input you would like to reference. Your div for the validation doesn't know fullname.
Upvotes: 0
Reputation: 1953
The HTML *ngIf can't locate user_name.invalid
(same for the fullname.invalid) as they aren't variables contained in the component. You have them listed in the formGroup but that isn't the same thing as declaring a user_name variable at the top of the class.
To make user_name, fullname and password available you would need to declare them like so:
user_name: string;
fullname: string;
password: string;
And then populate them in your code. This can get messy when you have essentially the same data now residing in two places.
Alternatively, you could use a function to return the value of control from the formGroup:
getUserName() {
return this.formGroup.controls['user_name'].value;
}
But the main thing to take away, is that controls specified in a formGroup aren't available to be displayed the same way a variable accessed via this
is.
Upvotes: 1
Reputation: 5118
You'll need to access the form control on the form object like this: registerForm.get('user_name').invalid
and so on, for each property (such as dirty
) and for each control in the form.
Another alternative is to create a getter in your component class for each form control:
get user_name() {
return this.registerForm.get('user_name');
Then you can keep your HTML as it is currently.
If you look at the example here: https://angular.io/guide/form-validation#built-in-validators they say:
This example adds a few getter methods. In a reactive form, you can always access any form control through the get method on its parent group, but sometimes it's useful to define getters as shorthands for the template.
In reference to getters for the form controls.
Upvotes: 1