I am trying to create an update form in Angular. I have tried many things but then again im not very familiar with Angular to begin with. This seems pretty straight forward though, I am getting the data using the ngOnInit()
method (which is returning the correct data). The user data is displayed in the input fields but then the error comes up.
This is the error that I get in the console:
UpdateComponent.html:6 ERROR TypeError: Cannot read property 'firstName' of undefined
at Object.eval [as updateDirectives] (UpdateComponent.html:6)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:11914)
at checkAndUpdateView (core.js:11307)
at callViewAction (core.js:11548)
at execComponentViewsAction (core.js:11490)
at checkAndUpdateView (core.js:11313)
at callViewAction (core.js:11548)
at execEmbeddedViewsAction (core.js:11511)
at checkAndUpdateView (core.js:11308)
at callViewAction (core.js:11548)
My update.component.html
file:
<div>
<h2 class="page-header">Edit your Profile</h2>
<form (ngSubmit)="onUpdateSubmit(user)" novalidate>
<div class="form-group">
<label for="firstName">First Name</label>
<input type="text" [(ngModel)]="user.firstName" name="firstName" class="form-control" id="firstName" placeholder="First Name">
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input type="text" [(ngModel)]="user.lastName" name="lastName" class="form-control" id="lastName" placeholder="Last Name">
</div>
<div class="form-group">
<label for="age">Age</label>
<input type="number" [(ngModel)]="user.age" name="age" class="form-control" id="age" placeholder="Age" min="0" max="200">
</div>
<div class="form-group">
<label for="favoriteFood">What is your Favorite Food?</label>
<input type="text" [(ngModel)]="user.favoriteFood" name="favoriteFood" class="form-control" id="favoriteFood" placeholder="Favorite Food">
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" [(ngModel)]="user.username" name="username" class="form-control" id="username" placeholder="Username">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" [(ngModel)]="user.email" name="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" [(ngModel)]="password" name="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div><div>
<h2 class="page-header">Edit your Profile</h2>
<form (ngSubmit)="onUpdateSubmit(user)" novalidate>
<div class="form-group">
<label for="firstName">First Name</label>
<input type="text" [(ngModel)]="user.firstName" name="firstName" class="form-control" id="firstName" placeholder="First Name">
</div>
<div class="form-group">
<label for="lastName">Last Name</label>
<input type="text" [(ngModel)]="user.lastName" name="lastName" class="form-control" id="lastName" placeholder="Last Name">
</div>
<div class="form-group">
<label for="age">Age</label>
<input type="number" [(ngModel)]="user.age" name="age" class="form-control" id="age" placeholder="Age" min="0" max="200">
</div>
<div class="form-group">
<label for="favoriteFood">What is your Favorite Food?</label>
<input type="text" [(ngModel)]="user.favoriteFood" name="favoriteFood" class="form-control" id="favoriteFood" placeholder="Favorite Food">
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" [(ngModel)]="user.username" name="username" class="form-control" id="username" placeholder="Username">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" [(ngModel)]="user.email" name="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" [(ngModel)]="password" name="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
My update.component.ts
file:
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../services/auth.service';
import { ValidateService } from '../../services/validate.service';
import { Router } from "@angular/router";
import { FlashMessagesService } from 'angular2-flash-messages';
@Component({
selector: 'app-update',
templateUrl: './update.component.html',
styleUrls: ['./update.component.css']
})
export class UpdateComponent implements OnInit {
user: Object;
constructor(
private authService: AuthService,
private validateService: ValidateService,
private router: Router,
private _flashMessagesService: FlashMessagesService
) { }
ngOnInit() {
this.authService.getProfile().subscribe(profile => {
this.user = profile.user;
},
err => {
console.log(err);
return false;
});
}
onUpdateSubmit(user) {
console.log("Component", user)
// Required Fields
if(!this.validateService.validateSignup(user)) {
this._flashMessagesService.show("Please fill in all fields", {cssClass: "alert-danger", timeout: 3000});
return false;
}
// Validate Email
if(!this.validateService.validateEmail(user.email)) {
this._flashMessagesService.show("Please use valid email", {cssClass: "alert-danger", timeout: 3000});
return false;
}
// Update user
this.authService.updateUser(user).subscribe(data => {
if(data.success) {
this._flashMessagesService.show("Update Success!", {cssClass: "alert-success", timeout: 3000});
this.router.navigate(["/profile"]);
} else {
this._flashMessagesService.show("Something went wrong", {cssClass: "alert-danger", timeout: 3000});
this.router.navigate(["/update"]);
}
});
}
}
This is because there is no firstName
returned in user data. Maybe it is undefined. To avoid the issue.
You'd better: 1. Check the user data in ngOnInit()
if it is returned. 2. Initial user data. e,g: user = { firstName: '' };
3. Check whether there is a delay when get user data from service
You are having a two way binding in your form , then why you need to pass the user on form submit. Try using as below
<form (ngSubmit)="onUpdateSubmit()" novalidate>
.
.
.
and use
onUpdateSubmit() {
console.log("Component", this.user);
.
.
.
}
Your error message is clear. Your user is populated by api call on ngOnInit
which however, may return a response after the html is loaded. While loading, your DOM expect user to the available but its undefined in your case. There are few ways you can fix this. First , folloow the usual standard, define your user like below in your constructor.
constructor(
private authService: AuthService,
private validateService: ValidateService,
private router: Router,
private _flashMessagesService: FlashMessagesService
) {
this.user = <Object>{};
}
Now your user is not undefined and even though user.name
might be , it will be briefly and error will not be thrown. Second option is, update your update.component.html
, load your DOM only when user is available or not undefined. To do this, add *ngIf in your first div
<div *ngIf="user">
<h2 class="page-header">Edit your Profile</h2>
<form (ngSubmit)="onUpdateSubmit(user)" novalidate>
........
.........
</form
</div>
Form the above, your form will not be loaded when user is undefined hence the need for user.name is avoided .
This is because there is no firstName
defined in user data. This is because at the time of your page loads, your user
object is not initialised. If there is no object assigned to this.user
in ngOnInit
it will return an exception. You can fix this in two ways. One method is to initialize the this.user
object at the beginning. It will return a blank form if there is no object is assigned to the user object in ngOnInit
but it won't return an exception. You can do it by simply initializing the user
object when defining the object or in the constructor.
when defining the object
user={}
or in constructor
this.user={}
Second method is, in case you want to display the form only if there are data you can use the *ngIf
to display the form only when the there are data in the user
object.
<div *ngIf="user">
<h2 class="page-header">Edit your Profile</h2>
<form (ngSubmit)="onUpdateSubmit(user)" novalidate>
........
.........
</form
</div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.