Reputation: 489
I have a stackblitz with a ngbTypeahead input for addresses. As you type it sends the string to the ArcGIS API, and provides a list of suggestions to populate the type ahead dropdown.
This was working with get but now I am using get<Array> since I am told it is better practice to return a type.
I have modified the service to:
@Injectable()
export class SuggestService {
constructor(private http: HttpClient) {}
search(term: string): Observable<Array<LocationSuggestion>> {
if (term === "") {
return of([]);
}
return this.http
.get<Array<LocationSuggestion>>(GIS_URL, { params: GIS_PARAMS.set("text", term) });
}
}
A sample of what is returned from the API:
{
"suggestions": [
{
"text": "Treasure Island, 3300 Las Vegas Blvd S, Las Vegas, NV, 89109, USA",
"magicKey": "dHA9MCNsb2M9MTYzNTU4NCNsbmc9MzMjcGw9ODQ1MzAwI2xicz0xNDozNTUwMTU1NA==",
"isCollection": false
},
{
"text": "Treasure Island-Las Vegas, 3300 Las Vegas Blvd S, Las Vegas, NV, 89109, USA",
"magicKey": "dHA9MCNsb2M9MTYzNTU4NCNsbmc9MzMjcGw9ODQ1NDkyI2xicz0xNDozNTUwMTYzMg==",
"isCollection": false
},
{
"text": "Treasure Island Parking, Mel Torme Way, Las Vegas, NV, 89109, USA",
"magicKey": "dHA9MCNsb2M9MTYzNTU5MyNsbmc9MzMjcGw9ODQ1NjQ3I2xicz0xNDozNTUwMTYxMw==",
"isCollection": false
},
{
"text": "Treasure Island, Las Vegas, NV, 89109, USA",
"magicKey": "dHA9MCNsb2M9MTYzNTU1MSNsbmc9MzMjcGw9ODQ0NTg2I2xicz0xNDozNTUwMTU1NA==",
"isCollection": false
},
{
"text": "Treasure Island Parking, Industrial Rd, Las Vegas, NV, 89109, USA",
"magicKey": "dHA9MCNsb2M9MTYzNTU1MiNsbmc9MzMjcGw9ODQ0NTk4I2xicz0xNDozNTUwMTYxMw==",
"isCollection": false
}
]
}
But the actual call to the service I do not understand:
NgbTyepaheadHttp Class
formatter = (result: any) => result.text as string;
search = (text$: Observable<string>) => // Is text$ a observable received from input?
text$.pipe( // Self explanatory
debounceTime(300),
distinctUntilChanged(),
tap(() => (this.searching = true)), // Sends message to UI searching?
switchMap(term => // What does Switch Map do?
this._service.search(term).pipe(
tap(() => (this.searchFailed = false)),
catchError(() => {
this.searchFailed = true;
return of([]);
})
)
),
tap(() => (this.searching = false))
);
I expect the formatter needs a type too, but when I change result:any
to result:LocationSuggestion
result.text is not existing?
Before I can modify the call to the service to work with a specific type - I need to understand the above code block better. It is hard to understand because of all the nesting.
Q: Which line actually returns the result of the search as the only return statement seems to be for an empty array?
I do not think the typeahead is getting an Array of LocationSuggestions because of this error in the console:
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
Upvotes: 1
Views: 760
Reputation: 21638
The call to the api returns an object that contains the array, not an array.
Change the api call to
return this.http
.get<GisLocationSuggestions>(GIS_URL, { params: GIS_PARAMS.set("text", term) })
.pipe(map(val => val.suggestions));
Fixed https://stackblitz.com/edit/angular-d5zmgq-r6vzye?file=src%2Fapp%2Ftypeahead-http.ts
Upvotes: 1