F.A
F.A

Reputation: 55

Angular8 TypeError: Cannot read property 'forEach' of undefined

Ive already searched a solution but none of them works.

After clicking on a button edit it redirects me to edit-event and I'm getting :

ERROR TypeError: Cannot read property 'categories' of undefined

  ngOnInit() {
    this.eventService
    .getEventById(this.route.snapshot.params.id)
    .subscribe((ev) => this.event = ev);

After the subscribe if I do this : console.log(this.event) it returns me undefined. Wherease .subscribe(console.log(ev)); returns me an object. Don't know why this.event = ev doesn't work Ive already used this in another component and the mapping works.

The service :

getEventById(id) {
    return this.httpClient.get<EventsDto>(this.urlevent + '?id=' + id);
  }

In edit-event.component.html, {{event.name}} is printed how is this possible if this.event is undefined as we've seen before with : .subscribe((ev) => this.event = ev)

Upvotes: 0

Views: 408

Answers (1)

nate-kumar
nate-kumar

Reputation: 1771

tl;dr - Group your asynchronous logic by calling this.http.get() inside of the button press function and apply any downstream logic within its subscribe() method


As you are dealing with asynchronous code, you have to take extra care to ensure that the asynchronous functions (e.g. your this.httpClient.get request) have returned the data before you try and interact with it, display it etc.

As you quite rightly mentioned, your .subscribe(console.log(ev)) is correctly logging data but your synchronous console.log(ev) is not. This is due to the fact that the sychronous console.log(ev) will be executed immediately after your this.httpClient.get() has been called. As it takes some time for the asynchronous data to be returned, the variable ev is still undefined at the point in time that the sychronous console.log(ev) is fired. Calling console.log(ev) from within your subscribe() block instead waits specifically for the data to be returned from the this.httpClient.get() before executing, guaranteeing that ev will have the data you requested (or an error).

With that in mind, a simple way to mitigate your issue would be to call the this.http.get() request inside the button click event and include any downstream functionality within the .subscribe() function. This will allow the compiler to guarantee that some data is available at the time that the subsequent functions are called.

.html

<button (click)="buttonClick()></button>

.ts

buttonClick() {
  this.eventService
    .getEventById(this.route.snapshot.params.id)
    .subscribe(ev => {
      this.event = ev
      // your code here, e.g. createEventsDto(ev)
    });

Upvotes: 1

Related Questions