1

In my angular project, I have a following setup:

API.ts: API functions to get data

...
export class dataAPI {
   info: any = null;

   getDataFromAPI(name){
     this.http.get(name)...
       .subscribe(data =>{
          this.info = data;  //This will have returned data
       }
   }  
}

Main.ts: Main page ts file where the API function is used

  import { dataAPI }  from '../API.ts';

  @Component({
     templateUrl: 'main_page.html'
  }) 

  export class mainPage{      
      returnedData: any;

      constructor(public myAPI: dataAPI){};

      ngOnInit(){
          this.returnedData = this.myAPI.getDataFromAPI('steve'); //????
      }        
  }

main_page.html: Need to show the returned data from API function

 <div class="main" *ngIf="returnedData">
     {{returnedData}}
 </div>   

Question

From API.ts file, this.info will need to somehow passed onto main.ts. How do I do this? Any help will be much appreciated!

Steve Kim
  • 5,293
  • 16
  • 54
  • 99
  • What is the output of this code ? – ZAhmed Aug 14 '17 at 07:40
  • 1
    Why not return an Observable from service function and subscribe from it at your component? refer https://stackoverflow.com/questions/45652646/get-string-value-from-observablestring-in-typescript-and-angular/45652811#45652811 – Pengyy Aug 14 '17 at 07:42
  • Seems like you are trying to return data from subscribe, which is not possible, so it's probably a dupe of [this](https://stackoverflow.com/questions/39295854/angular-2-how-to-return-data-from-subscribe) – AT82 Aug 14 '17 at 07:42
  • Don't subscribe from the service. **Return** the observable, and subscribe in the component, or in the view using the async pipe. – JB Nizet Aug 14 '17 at 07:43
  • The data returned is like a paragraph or phone number. Because there are many occasions and in many different files that I need to use the same api, I though I would make a function that I can use in multiple files. – Steve Kim Aug 14 '17 at 07:49
  • Yes, that is the purpose of a service ... to share functionality across many places in the application. – DeborahK Aug 14 '17 at 08:01

2 Answers2

4

Option 1

I would do something like this

getDataFromAPI(name){
   //do not subscribe in this service! Return the observable.
    return this.http.get(name)...

   } 

And in your mainPage

export class mainPage{      
      returnedData: any;

      constructor(public myAPI: dataAPI){};

      ngOnInit(){
         this.myAPI.getDataFromAPI('steve')
          .subscribe( data=>{
             this.returnedData = data; //SUBSCRIBE HERE
           }); 
      }        
  }

Option 2 Almost the same with option 1, but using an async pipe like this

export class mainPage{      
      returnedData$ : Observable<any>;

      constructor(public myAPI: dataAPI){};

      ngOnInit(){
         this.returnedData$ = this.myAPI.getDataFromAPI('steve');
      }        
  }

And in your template

<div class="main">
     {{ returnedData$ | async)}}
 </div>   

Option 3 Here's another option and something that I would not recommend. Since you declare the service as public, you can use it as well in your template like this directly .

 <div class="main" *ngIf="myAPI.info">
    {{returnedData$ | async}}
 </div>   

and declare your info as public in your service.

brijmcq
  • 3,354
  • 2
  • 17
  • 34
  • But NOTE: The above will only work if API.ts is a service. It's not clear from the OP that it is a service and not just a simple class. – DeborahK Aug 14 '17 at 08:00
  • @DeborahK thank you for commenting. I didn't notice that. I just assumed that it is a service. I agree that the question was not clear whether it was from a service or class – brijmcq Aug 14 '17 at 08:53
2

Starting here may be helpful: https://angular.io/guide/http

Note that the sample code in the Angular docs does not yet show the "best practice" of using a service for the Http calls. But it does explain how http works and returns an observable to your code.

Here is an example service that returns a product. You can adjust this to meet your needs:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';

import { IProduct } from './product';

@Injectable()
export class ProductService {
    private _productUrl = './api/products/products.json';

    constructor(private _http: HttpClient) { }

    getProducts(): Observable<IProduct[]> {
        return this._http.get<IProduct[]>(this._productUrl)
            .do(data => console.log('All: ' + JSON.stringify(data)))
            .catch(this.handleError);
    }

    private handleError(err: HttpErrorResponse) {
        // in a real world app, we may send the server to some remote logging infrastructure
        // instead of just logging it to the console
        let errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
        console.error(errorMessage);
        return Observable.throw(errorMessage);
    }
}

And here is the component code that calls the service, receiving the data:

import { Component, OnInit } from '@angular/core';

import { IProduct } from './product';
import { ProductService } from './product.service';

@Component({
    templateUrl: './product-list.component.html'
})
export class ProductListComponent implements OnInit {
    products: IProduct[] = [];
    errorMessage = '';

    constructor(private _productService: ProductService) {

    }

    ngOnInit(): void {
        this._productService.getProducts()
                .subscribe(products => this.products = products;,
                           error => this.errorMessage = <any>error);
    }
}
DeborahK
  • 57,520
  • 12
  • 104
  • 129