Reputation: 1443
When 1st API loaded, I need to get value and pass it to second API to get details. With my current code variable become undefined. Here is my code:
app.ts
export class DailyEndorsementComponent implements OnInit {
public selectedShop: string;
shop: string[];
shopData: ShopData;
constructor(private endorsementService: EndorsementService) {}
ngOnInit() {
this.getDates();
this.loadShopList();
}
setPayload() {
return {
'startDate': this.fromDate,
'endDate': this.toDate,
'settlementBank': this.selectedShop,
}
}
getDates(range: any) {
this.fromDate = this.datePipe.transform(range.fromDate, 'yyyy-MM-dd');
this.toDate = this.datePipe.transform(range.toDate, 'yyyy-MM-dd');
this.loadMerchantDailyEndorsement();
}
loadShopList() {
this.endorsementService.shopList()
.subscribe(response => {
this.shop = response;
this.selectedShop = this.banks[0];
})
}
loadMerchantDailyEndorsement() {
this.endorsementService.getMerchantEndorsement(this.setPayload())
.subscribe((response: EndorsementResponseInterface) => {
this.shopData = response;
}
}
app.service.ts
export class EndorsementService extends RestService {
private BASE_URL_MERCHANT: string = '/settlement/merchant/settlement';
private BASE_URL_CUSTOMER: string = '/settlement/customer/settlement';
private headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('token')
});
constructor(protected httpClient: HttpClient,
protected injector: Injector,
protected snackBar: MatSnackBar) {
super(injector);
}
getMerchantEndorsement(body: any): Observable < EndorsementResponseInterface > {
return this.post < EndorsementResponseInterface >
(this.getFullUrl(`${this.BASE_URL_MERCHANT}/daily/get`), body, {
headers: this.headers
});
}
shopList(): Observable < string[] > {
return this.get < string[] >
(this.getFullUrl(`/settlement/settlementbanks`), {
headers: this.headers
});
}
}
I need to get value from loadShopList() then call and pass it to loadMerchantDailyEndorsement(). Please let me know if I missed out anything.
Upvotes: 4
Views: 11689
Reputation: 1066
You can do this using the mergeMap operator of rxjs.
Angular 4.3+ (using HttpClientModule) and RxJS 6+
getMerchantEndorsement(body): Observable<EndorsementResponseInterface> {
this.http.post(this.getFullUrl(`/settlement/settlementbanks`, {headers})
.pipe(mergeMap(character => this.http.get(character.shopId)));
}
For reference, you can view here
Upvotes: 0
Reputation: 6844
There are a few different ways you could accomplish this, but I believe you should leverage Promises.
export class DailyEndorsementComponent implements OnInit {
public selectedShop: string;
shop: string[];
shopData: ShopData;
constructor(private endorsementService: EndorsementService) {}
ngOnInit() {
this.loadShopList().then(() => {
this.getDates();
});
}
setPayload() {
return {
'startDate': this.fromDate,
'endDate': this.toDate,
'settlementBank': this.selectedShop,
}
}
getDates(range: any) {
this.fromDate = this.datePipe.transform(range.fromDate, 'yyyy-MM-dd');
this.toDate = this.datePipe.transform(range.toDate, 'yyyy-MM-dd');
this.loadMerchantDailyEndorsement();
}
loadShopList() {
return new Promise((resolve) => {
this.endorsementService.shopList()
.subscribe(response => {
this.shop = response;
this.selectedShop = this.banks[0];
resolve();
});
});
}
loadMerchantDailyEndorsement() {
this.endorsementService.getMerchantEndorsement(this.setPayload())
.subscribe((response: EndorsementResponseInterface) => {
this.shopData = response;
}
}
This seems to be what you want - wait until the first request completes before starting the second.
Upvotes: 0
Reputation: 7875
for that you need to flat your observable of observable.
Goal is to have 1 observable (here this.endorsementService.shopList
) which will be mergeMap
to another observable (here this.endorsementService.getMerchantEndorsement
)
that means anytime shopList
observable will emit new data on stream :
getMerchantEndorsement
base on the current value of shopList
shopList
to getMerchantEndorsement
stream.i have create dummy demo to ilustrate :
// Simple observable to emulate selected shop from list.
const shopDetail$ = of({
shop: {
id: 1,
name: 'My little poney Inc'
}
}).pipe(delay(100)); // Delay is added to emulate api call delay. is optional
// Factory for remote data : simple function which emulate http request.
// Base on current id parameter, will return observable of marchandize detail.
const getMarchandizeDetail$ = (id: number) => {
const dummyDb = {
'1': {marchandize : ['poney 1', 'poney 2', 'poney 3']},
'2': {marchandize : ['element 1', 'element 2', 'element 3']},
};
return of(dummyDb[id]);
};
// When current shop change...
shopDetail$.pipe(mergeMap(
info => {
// We subscribe to http call : getMarchandizeDetail base on the current shop id.
return getMarchandizeDetail$(info.shop.id)
}
)).subscribe(console.log);
Upvotes: 4