html - Angular 8 :ERROR TypeError: No se puede leer la propiedad 'invalid' de undefined
¿Alguien puede explicar qué significa esto en realidad? Soy nuevo en Angular y actualmente estoy usando Angular 8 y esto aparece en mi consola.
ERROR TypeError: No se puede leer la propiedad 'invalid' de 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)
Aquí está mi código fuente que implica la página que tiene los errores
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>
Quizás tuve algún problema con la definición de variables, pero en realidad definí arrays de variables usadas para mi formulario en la primera parte de mi ts. Tal vez perdí algo, ¿qué es eso?
Respuesta #1
Necesitarás acceder al control del formulario en el objeto del formulario así: registerForm.get('user_name').invalid y así sucesivamente, para cada propiedad (como dirty) y para cada control en el formulario.
Otra alternativa es crear un getter en la clase de tu componente para cada control del formulario:
get user_name() {
return this.registerForm.get('user_name');
Entonces puedes mantener tu HTML tal como está actualmente.
Si miras el ejemplo aquí: https://angular.io/guide/form-validation#built-in-validators ellos dicen:
Este ejemplo agrega algunos métodos getter. En un formulario reactivo, siempre puedes acceder a cualquier control del formulario a través del método get en su grupo padre, pero a veces es útil definir getters como atajos para la plantilla.
En referencia a los getters de los controles del formulario.
Respuesta #2
El HTML *ngIf no puede localizar user_name.invalid (lo mismo para fullname.invalid) ya que no son variables contenidas en el componente. Las tienes listadas en el formGroup, pero eso no es lo mismo que declarar una variable user_name en la parte superior de la clase.
Para hacer que user_name, fullname y password estén disponibles, necesitarías declararlos de la siguiente manera:
user_name: string;
fullname: string;
password: string;
Y luego rellenarlos en tu código. Esto puede volverse complicado cuando esencialmente tienes los mismos datos ahora residiendo en dos lugares.
Alternativamente, podrías usar una función para devolver el valor del control desde el formGroup:
getUserName() {
return this.formGroup.controls['user_name'].value;
}
Pero lo principal que hay que recordar es que los controles especificados en un formGroup no están disponibles para mostrarse de la misma manera que una variable accesible mediante this.
