Reputation: 300
import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
// Import RxJs required methods
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch'
@Injectable()
export class EquipmentService{
data: any;
constructor(private http:Http){
}
getDefaultEquipment(){
this.http.get('./app/SaveData/equipmentTest.json')
.map((res:Response) => res.json())
.subscribe(data => { this.data = data},
err => console.error(err),
() => console.log(this.data));
}
}
Reading data from a file, The important bit is getDefaultEquipment()
.
If you see the last console.log(this.data) the data is correct, it's exactly what I need. But if I return this.http.get(... () => {return this.data})
i get undefined. How do I get at and return this.data??
Obviously if I write another return such as the following, the observable hasn't completed yet, so it will return the empty data: any.
//clearly won't work because the get hasn't returned yet
getDefaultEquipment(){
this.http.get(...data => {this.data = data}...);
return this.data;
}
Upvotes: 1
Views: 6157
Reputation: 121
The following would be my take on it. Untested but the concept is solid. This would save you a lot of boilerplate code because of the async
pipe which basically eats Observables
. If you need to do some transformations then that would be possible also before returning the observable. You could either do that in the service, or you could do it in the component. Just remember on thing about Observables
, be sure to use the .share()
operator if you have multiple subscribers, or else you would execute (in this case) the http.get
once for each subscriber. The same goes for the .do
operator which can come in handy, but also acts like a subscriber.
I would recommend reading up on RxJs and take a look at the example from angulars website concerning usages of the async pipe.
The Angular AsyncPipe is an interesting example of an impure pipe. The AsyncPipe accepts a Promise or Observable as input and subscribes to the input automatically, eventually returning the emitted value(s).
equipment.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
export interface Equipment {
name: string;
id: string;
}
@Injectable()
export class EquipmentService {
constructor(private http:Http){}
public getDefaultEquipment(): Observable<Equipment[]> {
return this.http
.get('./app/SaveData/equipmentTest.json')
.map((res:Response) => res.json());
}
}
equipment-list.component.ts
import { Component, OnInit } from "@angular/core";
import { EquipmentService, Equipment } from "./services/equipment.service";
import { Observable } from 'rxjs/Rx';
@Component({
selector: 'equipment-list',
templateUrl: './equipment-list.component.html',
styleUrls: ['./equipment-list.component.css'],
providers:[
EquipmentService
]
})
export default class EquipmentComponent {
constructor(private service: EquipmentService) {}
public get equipment():Observable<Equipment[]> {
return this.service.getDefaultEquipment();
}
}
equipment-list.component.html
<ul>
<li *ngFor="item of (equipment | async)>
<span>{{item.id}}</span>
<span>{{item.name}}
</li>
</ul>
Upvotes: 4