-1

So I'm trying to use an object in my html page, for this I want to get the object from my api and put it in a variable to later use its data. My API works fine, it returns the Parking object and when I log it it shows the needed data. When I try to assign that object to a variable and log that variable it gives me UNDEFINED.

export class ParkingdetailsComponent implements OnInit {
  parking: Parking;
  id: number;
  constructor(
    private _route: ActivatedRoute,
    private _pds: ParkingDataService) { }

  ngOnInit(): void {
    this._route.paramMap.subscribe(params =>{
      this.id = parseInt(params.get('id'));
    });

    this._pds.getParking$(this.id).subscribe((parking: Parking) =>{
      console.log(parking); //logs the Parking object
      this.parking = parking; 
    });
    console.log(this.parking) //logs UNDEFINED
  }
}

Okay so I fixed my issue, it didn't have anything to do with the subscribe part, it did do what I wanted it to do, the issue was in my HTML I called the objects data with {{ parking.name }} ... forgot the "this." should have been {{ this.parking.name }}

Posting it for others who might stumble on the same issue.

JVK
  • 88
  • 2
  • 14
  • You're missing the point that the subscribe is effectively asynchronous logic, and will not happen until the observable returned from `getParking` is given a message. – Taplar Apr 29 '20 at 16:48
  • can you please elaborate on this, I'm new to angular so I'd love to understand more about it, but from this reply I don't realy know what you mean, sorry – JVK Apr 29 '20 at 16:51
  • 1
    `subscribe()` is an observable method. What it is doing is saying, hey, at some point in the future, this observable will be given a message. When that happens, I want to know about it, because I subscribed to you. So the logic in the subscribe will only happen once a message is received. It is very similar to how event handlers work, the logic only happening in the future when the event actually happens. – Taplar Apr 29 '20 at 16:53
  • 1
    This isn't anything tightly related to Angular. Start [here](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) and try to understand asynchronous operations. Because that is what you have here - the line `this.parking = parking` is not going to run at the same point in time as `console.log(this.parking)`. – VLAZ Apr 29 '20 at 16:53

4 Answers4

1

The usage of console.log(this.parking) is in the wrong place.

It should have been inside the subscribe() call to show you the data of this.parking. The getParking returns an observable so this is an async call, meaning whatever happens inside the subscribe call happens after the getParking API call has completed the execution. The code running after the subscribe call, runs without waiting for the data to arrive.

You can check out https://blog.logrocket.com/understanding-rxjs-observables/ for this purpose.

If you have worked with old school AJAX calls, you would write the console.log inside the AJAX onreadystatechange callback function. This is similar to the async behaviour of the observable, you can say. The onreadystatechange will fire when the state is changed. Likewise, a subscribe gets fired when the observable receives a next value.

0

Your console.log is executed immidiately in ngOnInit(). When you subscibe to a value the body of the subscription will execute a little bit later when a response is emitted by the observable. This should work:

export class ParkingdetailsComponent implements OnInit {
  parking: Parking;
  id: number;
  constructor(
    private _route: ActivatedRoute,
    private _pds: ParkingDataService) { }

  ngOnInit(): void {
    this._route.paramMap.subscribe(params =>{
      this.id = parseInt(params.get('id'));
    });

    this._pds.getParking$(this.id).subscribe((parking: Parking) =>{
      console.log(parking); //logs the Parking object
      this.parking = parking; 
      console.log(this.parking) //logs the Parking object
    });
  }
}

PS: Also keep this in consideration in your template. One solution would be *ngIf='parking'.

Rob Monhemius
  • 4,822
  • 2
  • 17
  • 49
0

When you subscribe the calculation required by the data should be done inside the subscription function ie,

   ngOnInit(): void {
    this._route.paramMap.subscribe(params =>{
      this.id = parseInt(params.get('id'));
    });

    this._pds.getParking$(this.id).subscribe((parking: Parking) =>{
      console.log(parking); //logs the Parking object
      this.parking = parking; 
      console.log(this.parking) //should be here
    });
    console.log(this.parking) //logs UNDEFINED
   }

because subscribing is async activity and hence execution will be done only after subscription fn receives when observable emits new data. Code return outside this will be executed sequentially in the javascript main thread.

Arun Mohan
  • 1,207
  • 1
  • 5
  • 11
0

So the issue here was not located in my typescript files, I didnt call my object's data correctly in my html file, I used {{ parking.name }} where it should have been {{ this.parking.name }}

anyways, thanks for the help everyone :)

JVK
  • 88
  • 2
  • 14