0

I am confused by what is happening in a section of my app. I have a component that uses ngOnChanges. ngOnchanges fires right before ngOnInit when the component loads. Both ngOnChanges and ngOnInit call a certain method (fetchResults) that calls an api service to get some data using an observable return. I have a tap on my call to the service to console log the returned data and also a breakpoint in vs for the api method that gets called.

When the initial call to fetchResults is made from the ngOnChanges hook, the service does not return any data and the api breakpoint is not hit. However, when the ngOnInit hook is triggered and the fetchResults is called a second time, the api breakpoint is hit and the console log displays the returned data.

Why is this happening? I am expecting any call to fetchResults to hit the api and return data. I have validated that the required param is being passed. The call from ngOnChanges and the the call from ngOnInit are identical.

Sample code:

  ngOnInit() {
    console.log('fetchResults called from ngOnInit')
    this.fetchResults(this.itemId);
  }

  ngOnChanges(changes: SimpleChanges) {
    console.log('ngOnChanges called with changes value: ', changes)
    this.fetchResults(changes['propName'].currentValue)
  }

fetchResults(itemId){
    console.log('fetchResults function called with competitionId: ', itemId)
    
    this.resultList$ = this.dataservice.getResults(itemId)
      .pipe( 
        map( result => {
          return result.map(
            item => {
              return item;
            }
          )
        }),
        tap(val => console.log(' fetchResults function - the value of returned result object: ', val))
      )
  }

Result Component Html with async binding:

... this.resultList$ | async" ...
mo_maat
  • 2,110
  • 12
  • 44
  • 72

1 Answers1

0

I guess that second time fetchResults method is called (when ngOnChanges executes it), your observable attribute resultList$ is "re-assigned" to a new observable object.


Anyway, if you want to test if you really are getting data or not both times, change your fetchResults method to get a different subscription any time (just for testing):

fetchResults(itemId){
    console.log('fetchResults function called with competitionId: ', itemId)
    
    this.dataservice.getResults(itemId)
      .pipe( 
        map( result => {
          return result.map(
            item => {
              return item;
            }
          )
        })
      ).subscribe(
         val => console.log(' fetchResults function - the value of returned result object: ', val)
      )}

Finally, if you want to "fix" it, you could do something like this:

// In your declaration of Class attributes:
get resultList$(itemId){

   return this.dataservice.getResults(itemId)
      .pipe( 
        map( result => {
          return result.map(
            item => {
              return item;
            }
          )
        }),
        tap(val => console.log(' fetchResults function - the value of returned result object: ', val))
   );

}

Class...

Cosntructor....

ngOnInit() {
    console.log('fetchResults called from ngOnInit')
    this.resultList$ = this.itemId;
}

ngOnChanges(changes: SimpleChanges) {
    console.log('ngOnChanges called with changes value: ', changes)
    this.resultList$ = changes['propName'].currentValue);
}



  • I made an edit to specify the async binding. I also tried your suggestion to test and indeed the api is now being called twice as I would expect. Why is that not happening when I use the async binding? – mo_maat Dec 15 '21 at 17:04
  • (ok, as I thought...) You can see the way at the beggining of my answer: When NgOnIt execute the fetchResults method (I mean, the second time that method is executed), resultList$ is "re-assigned" to a new observable object, so the first assignation is lost... So you only can get the values of the second time. – Juan Vicente Berzosa Tejero Dec 15 '21 at 17:14
  • I've just edited my answer with a possible solution that fits your requeriments. Give it a try and good luck! – Juan Vicente Berzosa Tejero Dec 15 '21 at 17:26
  • Sorry but I think you have it backwards. The first call is from `ngOnChanges`. The second call is from `ngOnInit`. The first call does not hit the api. The second call does. I want to know why the first call does not trigger the api when I am binding to the tamplate using async without using a `subscribe`. – mo_maat Dec 15 '21 at 20:43