Using angular Typeahead (ui.bootstrap.typeahead) requires a list of objects which it will display in the ui component with HTML
Problem
Returning promise
from service to component (1.5 style controller, view, bindings)
Controller function uses the returned promise
from the service and performs the then
logic and returns the array
of objects
Typeahead does not process the array... performing a console log, you can see the array.
If I statically pass the same array of objects without using the service method then the functionality works
HTML
<input type="text" ng-model="$ctrl.search.term" ng-disabled="!$ctrl.search.type"
typeahead-wait-ms="600"
placeholder="Search..."
uib-typeahead="res as res.name for res in $ctrl.submit($viewValue)"
typeahead-no-results="noResults" class="form-control" required>
<i ng-show="loadingLocations" class="icon ion-refresh"></i>
<div ng-show="noResults">
<i class="icon ion-close"></i> No Results Found
</div>
<select class="form-control custom-select-md"
ng-model="$ctrl.search.type"
placeholder="Type"
required>
<option value="" disabled selected>Select Type?</option>
<option value="car">car</option>
<option value="van">van</option>
</select>
Component (controller, view )
//submit search for issuers or issuedCard
submit() {
this.isSubmitting = true;
this._SearchService.performSearch(this.search)
.then(
(resp) => {
//e.g. [{id:1, name:'test'}]
console.log('Search Result', resp);
return resp;
},
(err) => {
console.log('Error Search', err);
this.reset(false);
this.errors = err;
return [];
}
);
//Comment out method above to see this static data returning and working as should be :'(
//return [{id:865,issuer: {},name:"British Testing"},
// {id:866,issuer: {},name:"American Testing"}];
}
Service
performSearch(searchData) {
console.log('Search Qry', searchData);
let deferred = this._$q.defer();
if(!this.isValidSearch(searchData)) {
deferred.reject({status:400, error: 'Bad Request', message:'invalid data'});
return deferred.promise;
}
let searchURI = (searchData.type === 'car' ? 'van' : 'issuer');
this._$http({
url: `${this._AppConstants.api}/${this._AppConstants[searchURI]['search']}`,
method: 'GET',
params: {
name: searchData.term
}
}).then(
(resp) => {
console.log('Search Data', resp);
this.result.term = searchData.term;
this.result.type = searchURI;
deferred.resolve(resp.data[this._AppConstants[searchURI]['searchResp']]);
},
(err) => {
console.log('Error performing search', err);
deferred.reject(err.data);
}
);
return deferred.promise;
}
You're using
res as res.name for res in $ctrl.submit($viewValue)
What comes after the in
is supposed to be an array, or a promise of array.
But it's not. It's what returned by $ctrl.submit()
. And this method doesn't return anything:
submit() {
this.isSubmitting = true;
// no return here
this._SearchService.performSearch(this.search)
.then(
(resp) => {
//e.g. [{id:1, name:'test'}]
console.log('Search Result', resp);
return resp;
},
(err) => {
console.log('Error Search', err);
this.reset(false);
this.errors = err;
return [];
}
);
// no return here
}
The only return statements return from the function passed to then()
, and are executed asynchronously, after the submit()
method has returned nothing (i.e. undefined
).
So, to be short, you need to return the promise:
return this._SearchService.performSearch(this.search) ...
Note that your service method could be reduced and cleaner if you used promise chaining, instead of the resolve/reject anti-pattern:
performSearch(searchData) {
console.log('Search Qry', searchData);
if(!this.isValidSearch(searchData)) {
return $q.reject({status:400, error: 'Bad Request', message:'invalid data'});
}
let searchURI = (searchData.type === 'car' ? 'van' : 'issuer');
return this._$http.get(`${this._AppConstants.api}/${this._AppConstants[searchURI]['search']}`, { params: {name: searchData.term) } }).then(
resp => {
console.log('Search Data', resp);
this.result.term = searchData.term;
this.result.type = searchURI;
return resp.data[this._AppConstants[searchURI]['searchResp']]);
}).catch(resp => {
console.log('Error Search', err);
this.reset(false);
this.errors = err;
return $q.reject([]);
});
}