Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get string value from Observable<string> in typescript and Angular

I want to get string value from Observable and return the value from the function to the caller function.

For eg: I have array of keys and would like to fetch the value (string) of all key one by one and display it html component which has menu bar.

Here are the ts files:

key-list.component.ts

public data = [ { 'key': 1, 'value' : this.getValue(1)}, 
                { 'key': 2, 'value' : this.getValue(2)}, 
                ...
              ];

private getValue(key: number): string {
    return this.keyService.find(key).subscribe(response => {
         return response;
    });
}

keyService.ts

...
public find(key:number): Observable<any> {
  return this.http.get(`/api/keys/${key}`).map(res => res.json() || {});
}
...

I want to display all the values in the html component. But getting error in key-list.component.ts that observable into type string.

How I can solve this subscription methodolgy and make sure that getValue should always return string, and make it flawless.

One of the solution is:

private getValue(key: number): string {
        let result: string;
        this.keyService.find(key).subscribe(res => result = res);
        return result;
    }

The above solution doesn't work always. What are the alternatives solution for this kind of problem?

like image 831
virsha Avatar asked Dec 11 '22 10:12

virsha


1 Answers

You are trying to return Observable from function getValue, and return response or return result won't work because request for http.get is asynchronous.

Here are some options what you can do:

Option1: using Async Pipe at your template to subscribe for result of http.get and remove subscribe part from function getValue.

<div *ngFor="let item of data">
  <span>{{item.value | async}}</span>
</div>

// return Observable and subscribe by async pipe at template
private getValue(key: number): string {
  return this.keyService.find(key);
}

Option2: Define the array data without value field and update its value field later. But be careful that the value field will be undefined unless you get response from this.keyService.find(key).

public data = [
  { 'key': 1}, 
  { 'key': 2}, 
  ...
];

constructor() {
  this.data.forEach(item => {
    this.keyService.find(item.key).subscribe(response => {
      item.value = response;    // update value field here.
    });
  });
}

// here getValue function is no longer necessary.

Hope this will help.


UPDATE from OP

With some slight changes in the above option1 it worked like charm.

Here are the changes:

<div *ngFor="let item of data">
  <span>{{ getValue(item.key) | async}}</span>
</div>

public getValue(key: number): any {
  return this.keyService.find(key);
}

Thanks for reminding to use Async Pipe @Pengyy (From OP)

like image 50
Pengyy Avatar answered Dec 22 '22 00:12

Pengyy