Belal Othman Belal Othman - 3 months ago 33
AngularJS Question

using autocomplete to bring data from DB with angularjs material

I want to use autocomplete to bring data from DB
in my application I have more than 150 companies and the user must select one of them so I want to use autocomplete
so when the user write 2 letters in the text field I want to display the companies that start with these 2 leters.
I used the example floating label from here https://material.angularjs.org/latest/demo/autocomplete and modified it just like that

* Search for states... use $timeout to simulate
* remote dataservice call.
*/
function querySearch (query) {
var results = createFilterFor(query);
var deferred = $q.defer();
$timeout(function () { deferred.resolve( results ); }, Math.random() * 1000, false);
return deferred.promise;
}



* filterCompany function return the company that start with cmompanycode
*/
function createFilterFor (companyCode) {
service.filterCompany(companyCode).then(function (response) {
return response.data.companies;

});
}


and this is the html

<div class="col-sm-2" ng-class="{ 'has-error': form.company.$dirty && form.company.$error.required }">
<md-input-container class="md-block">
<md-autocomplete flex="" required="" md-input-name="autocompleteField" md-input-minlength="2" md-input-maxlength="18" md-no-cache="ul.noCache" md-selected-item="ul.selectedItem" md-search-text="ul.searchText" md-items="item in ul.querySearch(ul.searchText)" md-item-text="item.display" md-floating-label="Favorite state">
<md-item-template>
<span md-highlight-text="ul.searchText">{{item.display}}</span>
</md-item-template>
</md-autocomplete>
</md-input-container>
</div>


but when I run the code I get

angular.js:12520 TypeError: Cannot read property 'length' of undefined
at W (angular-material.min.js:12)
at j (angular-material.min.js:12)
at o (angular-material.min.js:12)
at processQueue (angular.js:14792)
at angular.js:14808
at Scope.$eval (angular.js:16052)
at Scope.$digest (angular.js:15870)
at angular.js:16091
at completeOutstandingRequest (angular.js:5552)
at angular.js:5829


this is my service

function filterCompany(companyCode){
var deferred = $q.defer();

// simulate api call with $timeout
return $timeout(function () {
var encodeString = 'companyCode='+companyCode
return $http({
url: './getCompaniesAutoComplete',
method: "POST",
data: encodeString,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (response) {
response.message = 'getUser done Successfully';
}).error(function (response){
response.message = 'Error during getUser operation';
});
deferred.resolve({ success: true });
}, 1000);
return deferred.promise;
}

Answer

You're probably going through some CTRL+C CTRL+V misunderstanding and mixing up mock $timeout code from documentation with your own code.

Autocomplete accepts promise which gets resolved with array of items or simply the array. The promise never gets resolved with any response or data, because it gets resolved here in filterCompany: deferred.resolve({ success: true });

Get rid of the timeouts and manual deffers. Do something like:

function filterCompany(companyCode) {
    var encodeString = 'companyCode='+companyCode
    return $http({
        url: './getCompaniesAutoComplete',
        method: "POST",
        data: encodeString,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
    });
}

In your controller then:

function querySearch(companyCode) {
    return service.filterCompany(companyCode)
                .then(function (response) {
                     return response.data.companies;
                });
}

This is all you need.