I have an Angular 4 Component that is calling a Service to get data. Not the strangest of situations. After I retrieve the data and need to transform it and filter it. Apparently the way to do this nowadays is to use pipe.
In my Component:
ngOnInit(): void {
this.suService.getShippingUnitTypes().subscribe(res => {
console.log("Getting shipping unit types: ", res);
});
}
In my service:
getShippingUnitTypes(): any {
const convertToJson = map(value => (value as any).json().XXETA_GRID_STATIC_LOV);
const filterShippingUnit = filter(value => (value as any).LOV_TYPE == "SHIPPING_UNIT");
return this.http.get(
this.constantsService.LOOKUP_COLUMN_BATCH_URL
).pipe(convertToJson, filterShippingUnit);
}
The service imports the following:
import { Injectable } from '@angular/core';
import { Http, Response, RequestOptions, Headers, RequestMethod } from '@angular/http';
import { Observable, pipe } from 'rxjs/Rx';
import { map, filter } from 'rxjs/operators';
When debugging, the code never errors but simply never gets to the console.log() statement in the Component. If I remove the .pipe() and simply return the Observable the code logs what I would expect only without the transforming and filtering.
I'm very new to Rxjs and using Pipe. I'm obviously not understanding something.
Edited to Add Information:
I put tap into the pipe like such...
pipe(tap(console.log), convertToJson, tap(console.log), filterShippingUnit, tap(console.log))
I didn't know that tap existed but it is useful. The first two console logs give me what I would expect. The third one, right after the filterShippingUnit, doesn't do anything. It doesn't log a value at all. Not even null.
After convertToJson console.log spits out an array of 28 objects. One of the objects is:
{LOV_TYPE: "SHIPPING_UNIT", LOV_TAB_TYP_ITEM: Array(4)}
I would expect that object to be passed on based on the filterShippingUnit filter.
The problem is most likely here:
const filterShippingUnit = filter(value => (value as any).LOV_TYPE == "SHIPPING_UNIT");
Assuming that after parsing the body of the response to JSON, you get an array of type Foo
, where Foo
is defined as follows:
interface Foo {
LOV_TYPE: string;
fooProperty: string;
fooNumber: number;
}
You are trying to apply the filter to the array object, not to the objects contained in it.
You have two options: flatten the array and emit its values as singular events, and then put them together again as an array, or map the array to a new one; the second one being the easiest as follows:
const filterShippingUnit = map((list: Foo[])=> list
.filter(foo => foo.LOV_TYPE === "SHIPPING_UNIT"));
The first approach could be implemented as:
import { flatMap, toArray } from 'rxjs/operators';
return this.http.get(this.constantsService.LOOKUP_COLUMN_BATCH_URL)
.pipe(
flatMap(response => response.json() as Foo[])
map(foo => foo.LOV_TYPE === "SHIPPING_UNIT") // TypeScript will infer that foo is of type Foo
toArray
);
As its easy to notice that you are just starting in angular, I would suggest you the following: