59

This is What I Want To Do.

@Component({
   selector: "data",
   template: "<h1>{{ getData() }}</h1>"
})

export class DataComponent{
    this.http.get(path).subscribe({
       res => return res;
    })
}

If getData was called inside the DataComponent, You may suggest assign it to a variable like this.data = res and use i like {{data}}.But I needed to use like {{getData}} for my own purpose.Please suggest me?

Roham Rafii
  • 2,929
  • 7
  • 35
  • 49
tsadkan yitbarek
  • 1,360
  • 2
  • 11
  • 28

5 Answers5

62

You just can't return the value directly because it is an async call. An async call means it is running in the background (actually scheduled for later execution) while your code continues to execute.

You also can't have such code in the class directly. It needs to be moved into a method or the constructor.

What you can do is not to subscribe() directly but use an operator like map()

export class DataComponent{
    someMethod() {
      return this.http.get(path).map(res => {
        return res.json();
      });
    }
}

In addition, you can combine multiple .map with the same Observables as sometimes this improves code clarity and keeps things separate. Example:

validateResponse = (response) => validate(response);

parseJson = (json) => JSON.parse(json);

fetchUnits() {
    return this.http.get(requestUrl).map(this.validateResponse).map(this.parseJson);
}

This way an observable will be return the caller can subscribe to

export class DataComponent{
    someMethod() {
      return this.http.get(path).map(res => {
        return res.json();
      });
    }

    otherMethod() {
      this.someMethod().subscribe(data => this.data = data);
    }
}

The caller can also be in another class. Here it's just for brevity.

data => this.data = data

and

res => return res.json()

are arrow functions. They are similar to normal functions. These functions are passed to subscribe(...) or map(...) to be called from the observable when data arrives from the response. This is why data can't be returned directly, because when someMethod() is completed, the data wasn't received yet.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • You have a typo there, the first curly brakes should be after the "res =>" part, like this: `res => { return res; }` – Neyxo Feb 08 '18 at 22:12
  • HI Neyxo, could you please look once my issue: https://stackoverflow.com/questions/51551895/how-to-wait-return-statement-if-subscriber-not-completed-in-angular-2-4-6 – Er Vipin Sharma Jul 27 '18 at 07:34
7

Two ways I know of:

export class SomeComponent implements OnInit
{
    public localVar:any;

    ngOnInit(){
        this.http.get(Path).map(res => res.json()).subscribe(res => this.localVar = res);
    }
}

This will assign your result into local variable once information is returned just like in a promise. Then you just do {{ localVar }}

Another Way is to get a observable as a localVariable.

export class SomeComponent
{
    public localVar:any;

    constructor()
    {
        this.localVar = this.http.get(path).map(res => res.json());
    }
}

This way you're exposing a observable at which point you can do in your html is to use AsyncPipe {{ localVar | async }}

Please try it out and let me know if it works. Also, since angular 2 is pretty new, feel free to comment if something is wrong.

Hope it helps

qwerty_igor
  • 919
  • 8
  • 14
  • 1
    Really interesting info here @querty_igor What is the difference between this way and Subject() – Ben Racicot Mar 30 '17 at 18:49
  • if I am not mistaken, subject is type of observable anyways. it is used mostly to forward data, then your services or components subscribe to it but at that moment it is an observable. so Subject()->next() -> asObserable()-> observable.subscribe(). Haven't worked with angular 2 in a while. correct me if I am wrong. thnx – qwerty_igor Jun 27 '17 at 20:16
0

How about storing this one in a variable that can be used outside subscribe?

this.bindPlusService.getJSONCurrentRequestData(submission).map(data => {
    return delete JSON.parse(data)['$id'];
});
Abhinav Kumar
  • 2,883
  • 1
  • 17
  • 30
Julius
  • 1
0

Use pipe operator & subscribe to getData() or use async pipe in the tempate like..

  template.html
  <h1>{{ data$ | async }}</h1>

  component.ts
  data$ =  this.apiService.getData();

  api.service.ts
  getData() {
      return this._http
        .get(url)
        .pipe(
          map((res: any) => {
           return res;
            // or if you want to transform data
            // return transformRes(res);
        })
      );
   }

   transformRes(res) {return ...transform logic.}
Vikram Sapate
  • 1,087
  • 1
  • 11
  • 16
-2

I have used this way lots time ...

@Component({
   selector: "data",
   template: "<h1>{{ getData() }}</h1>"
})

export class DataComponent{
    this.http.get(path).subscribe({
       DataComponent.setSubscribeData(res);
    })
}


static subscribeData:any;
static setSubscribeData(data):any{
    DataComponent.subscribeData=data;
    return data;
}

use static keyword and save your time... here either you can use static variable or directly return object you want.... hope it will help you.. happy coding...

sajal rajabhoj
  • 507
  • 4
  • 14