Reputation: 5576
I have app in Angular 6 , user can follow, like, dislike etc . I am trying to save the data to the server via a post method.
When the user clicks eg follow I get the following error:
UserProfileComponent.html:27 ERROR TypeError: Cannot read property 'followers' of undefined
at UserProfileComponent.push../src/app/user-profile/user-profile.component.ts.UserProfileComponent.followButtonClick (user-profile.component.ts:46)
at Object.eval [as handleEvent] (UserProfileComponent.html:27)
at handleEvent (core.js:19324)
at callWithDebugContext (core.js:20418)
at Object.debugHandleEvent [as handleEvent] (core.js:20121)
at dispatchEvent (core.js:16773)
at core.js:17220
at HTMLButtonElement.<anonymous> (platform-browser.js:988)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:13842)
Here is json file in server:
{
"statuses": [{
"id": 1,
"statusId": 2,
"likes": 121,
"following": 723,
"followers": 4433
}]
}
Here is service I have :
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {Status } from '../model/statuses.model';
import { Comment } from '../model/comments.model';
@Injectable({
providedIn: 'root'
})
export class UserService {
status: Status[];
constructor(private http: HttpClient) { }
statusUrl = 'http://localhost:3000/statuses';
commentsUrl = 'http://localhost:3000/comments';
getStatuses() {
return this.http.get<Status[]>(this.statusUrl);
}
addStatus(status: Status) {
return this.http.patch(this.statusUrl, status);
}
addComments(comment: Comment) {
return this.http.post(this.commentsUrl, comment);
}
}
Here is component ts
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { UserService } from '../service/user.service';
import { Status } from '../model/statuses.model';
import { Comment } from '../model/comments.model';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss']
})
export class UserProfileComponent implements OnInit {
status: Status[];
comment: Comment[];
numberOflikes = 121;
numberOffollowing = 723;
numberOffollowers = 4433;
constructor(
private formBuilder: FormBuilder,
private http: HttpClient,
private userService: UserService
) {}
addForm: FormGroup;
ngOnInit() {
this.addForm = this.formBuilder.group({
id: [],
name: ['', Validators.required],
city: ['', Validators.required],
description: ['', Validators.required],
});
this.userService.getStatuses()
.subscribe(data => {
this.status = data;
console.log(data);
});
}
addComments() {
this.userService.addComments(this.addForm.value)
.subscribe(data => {
this.comment.push(this.addForm.value);
});
}
followButtonClick(statusId) {
this.status[statusId].followers++;
this.persistStatus(this.status[statusId]);
}
persistStatus(status) {
this.userService.addStatus(status);
}
}
Here is html
</div>
<ul class="profile_card-bottom" *ngFor="let stat of status">
<li class="likes">
<span class="assets-count">{{stat.followers}}</span>
<span class="assets-title">Likes</span>
</li>
</ul>
</div>
Here is model for status
export class Status {
id: number;
statusId: number;
like: number;
following: number;
followers: number;
}
What am I doing wrong in my code?
Upvotes: 0
Views: 7577
Reputation: 2966
as I see you did not pass argument to your followButtonClick()
method in html, so move your button in your *ngFor
loop and pass stat.id
as mentioned @selemmn
<h1>
Harvey Specter
<span class="heart reaction">
<i class="fa fa-heart heart" aria-hidden="true"(click)="followButtonClick(stat.id)"></i>
</span>
</h1>
and also change your followButtonClick()
method to this
followButtonClick(statusId) {
const statusToUpdate = this.status.filter(status => status.id === statusId)[0];
statusToUpdate.followers++;
this.persistStatus(statusToUpdate);
}
so as you didn't pass argument your statusId
is undefined
in followButtonClick()
so it tries to get this.status[undefined].followers++;
and throws error that can't find property followers
of undefined
Upvotes: 1
Reputation: 9678
You pass nothing as a parameter in the HTML part then based on the same function but with a parameter you proceed in the TS part.
Change this line to :
<button class="btn-follow" (click)="followButtonClick(stat.id)">Follow</button>
PS: Assuming it's named id
of course.
Upvotes: 1
Reputation: 2497
The problem seems that your userService is sending empty data, this empty data then loads into the status array. This should not happen.
You can either handle it in the userService (preferrably , which should b the code hosted at http://localhost:3000/statuses )
If you have no control on server side, you can fix their mistake when calling this.userService.getStatuses()
to check if the data is valid object and not an empty one.
Upvotes: 0
Reputation: 39482
Even though this.status
is an array, there's no gurantee that the index of a status and it's statusId
will be the same. So you might be getting an index that doesn't exist in your status
array and hence the undefined error
Try changing the implememtation of followButtonClick(statusId)
like this:
followButtonClick(statusId) {
const statusToUpdate = this.status.filter(status => status.statusId === statusId)[0];
statusToUpdate.followers++;
this.persistStatus(statusToUpdate);
}
Upvotes: 0