Search code examples
angularobservableangular-routerangular-httpclient

Call Observable on runtime and render the result


I have a View, where when clicked a button like this

  <a class="button" (click)="takeInpit(id)" routerLinkActive="activebutton"  >Request</a>

triggers this takeInput method

public takeInpit(Id:string): void{

    let navigationExtras: NavigationExtras = {
      queryParams: {
        "id":Id
      }
  };
  this.router.navigate(["request"], navigationExtras);
  }

Then I navigate to this component called request:

//takes parameters from container
  public constructor(private route: ActivatedRoute, private itemService: SingleItemService) {
    this.route.queryParams.subscribe(params => {
        this.requestedItem = params["id"];
        this.itemService.setIDs(this.requestedItem);
        this.itemService.getSingleItemRequest();
    });
    this.item = this.itemService.getName();
    //console.log(this.item);
    
}

where I'm calling this service with the idea that I can take dynamically data from an API

export class SingleItemService {

  urlSingle:string = 'http://localhost:8080/getSpecificItem?itemId=';
  item:any;
  
  constructor(private htpp: HttpClient){
  }

  public setIDs(id:string){
    this.urlSingle + id;
}

  public getSingleItemRequest():void{
     this.htpp.get<Item>(this.urlSingle).subscribe( data=>{
     this.item = data;
     console.log("data is", data);
     }
   );
   }

   public getName(): string{
      return this.item.name;
    
   }
}

and after that log the data at the request component View (the one that called the service basically)

<div ngIf* ="item"><div>{{item}}</div>
</div>

However the info is not logged. Checking the console i see this message:

ERROR Error: Uncaught (in promise): TypeError: this.item is undefined
getName@http://localhost:4200/main.js:368:9

so It tries to access the service's get method BEFORE the observable is done. How can I fix that?


Solution

  • In SingleItemService return Observable from getSingleItemRequest, use tap to assign response to item.

    import { tap } from 'rxjs/operators';
    
    public getSingleItemRequest():Observable<any>{
         return this.htpp.get<Item>(this.urlSingle).pipe(
            tap(data => this.item = data)
        );
    }
    

    In RequestComponent

    item = '';
    
    this.route.queryParams.subscribe(params => {
        this.requestedItem = params["id"];
        this.itemService.setIDs(this.requestedItem);
        this.itemService.getSingleItemRequest()
        .subscribe(_ => this.item = this.itemService.getName());
        // .subscribe(response => this.item = response.name);
    });