I am giving ajax call in md-search-text-changed
. So every time text is changed ajax call is done. But ajax takes time to give response and before even coming response it shows no data found and when response comes it does not get updated in dropdown even if array provided in md-items
is updated. I tried different methods to make ajax call even in md-items
but it doesn't work. Then i gave md-delay
of 5 sec then it rendered result but that is of previous search query. It does not update result for latest search query.
Can you at least show me proper working example of autocomplete with ajax call in md-search-text-changed
so that I'll get idea where I am going wrong or it's issue of md-autocomplete
.
Is there any way to show dropdown only when response is received?
I got it .. I wasn't returning promise correctly that is the reason why I am not getting results properly. Now it is working perfectly fine.
Hi @alphazhe , I'm having the exact same issue, would you mind posting your working code ?
Here's my markup and js:
<md-autocomplete md-no-cache="true" placeholder="Search for client"
md-selected-item="vm.client" md-search-text="vm.searchText" md-items="item in vm.clients"
md-search-text-change="vm.searchClients(vm.searchText)" md-item-text="item.name"
md-min-length="2" md-floating-label="Client">
<md-item-template>
<span md-highlight-text="vm.searchText" md-highlight-flags="^i">{{item.name}}</span>
</md-item-template>
</md-autocomplete>
this.searchClients = function(searchText) {
var deferred = _this.$qService.defer();
_this.dataService.searchClients(searchText).then(function(results) {
_this.clients = results.data;
deferred.resolve(results.data);
});
return deferred.promise;
};
And my data service:
this.searchClients = function(searchText) {
var config = {
url: "/api/Clients?searchText=" + searchText,
method: "GET",
headers: {
'Content-Type': "application/json; charset=utf-8"
}
};
return _this.$http(config);
};
Having the same issue. autocomplete list only updates for the previous query. ie- if i have a min character limit before query of 3, and i type 'cli' nothing happens. and when i type 'clin' it returns a list of results for 'cli'. the response from nominatum is obviously coming in after the list updates, but not sure how to fix this. js and html below. help would be much appreciated as i have been banging my head on the wall with this for ages.
<div ng-cloak id="searchBox">
<md-content class="md-padding" style="background-color:cornflowerblue">
<form>
<md-autocomplete
md-no-cache="noCache"
md-search-text-change="nominatimSearch()"
md-search-text="searchText"
md-items="place in result1"
md-delay="0"
md-min-length="3"
placeholder="Place Name">
<md-item-template>
<span md-highlight-text="searchTextNumber">{{place.display_name}}</span>
</md-item-template>
</md-autocomplete>
</form>
</md-content>
</div>
$scope.nominatimSearch = function() {
if ($scope.searchText.length > 2) {
// var deferred = $q.defer();
console.log('searching for place');
// $scope.googleAnalytics();
$http({
method: 'get',
url: 'http://nominatim.openstreetmap.org/search?q='+$scope.searchText+'&format=json&class=place&addressdetails=1'
})
.then(function successCallback(response) {
$scope.result1 = response.data;
console.log($scope.result1);
// return deferred.promise;
}, function errorCallback(response) {"sorry charlie...";
return $q.reject(response.data);
});
} else {
$scope.result1 = []
}
};
+1
+1
Use md-no-cache to invoke the search handler every time user types value in second autocomplete.
+1
+1
+1
Reopened based on community votes.
The reason autocomplete is not working for you as intended is because your query function should be inside the "md-items" directive (as opposed to being inside the "md-search-text-change").
The md-items directive takes an expression in the form of "item in results", but the results expression can also be a function which returns the results synchronously or asynchronously (this last part is currently missing in the docs).
...
md-search-text="ctrl.searchText"
md-items="item in ctrl.querySearch(ctrl.searchText)"
...
Hope this helps.
I'm having the same problem. Already tried a lot of possibilities and every one comes with the same issue.
<md-autocomplete
md-floating-label="{{'SEARCH' | translate}}"
ng-disabled="isDisabled"
md-no-cache="noCache"
md-selected-item="selectedItem"
md-search-text-change="searchTextChange(searchText)"
md-search-text="searchText"
md-selected-item-change="displaySearchedResult(item)"
md-items="item in querySearch(searchText)"
md-item-text="item.name"
md-delay="500"
md-min-length="3" class="searchinput">
<md-item-template>
<span md-highlight-text="searchText" md-highlight-flags="^i">{{item.name}}</span>
</md-item-template>
</md-autocomplete>
And my JS. AutocompleteSearch is a service, that return $http.post()
.
plugCrmApp.controller('SearchBarCtrl', ['$scope', '$rootScope', '$timeout', '$http', '$location', '$q', 'AutocompleteSearch', function($scope, $rootScope, $timeout, $http, $location, $q, AutocompleteSearch) {
$scope.results = [];
$scope.isDisabled = false;
$scope.noCache = true;
$scope.selectedItem = null;
$scope.searchText = null;
$scope.result = {};
$scope.querySearch = function(query) {
loadAll(query);
var results = query ? $scope.results.filter( createFilterFor(query) ) : $scope.results, deferred;
// console.info(results);
return results;
};
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
// console.info(lowercaseQuery);
return function filterFn(v) {
// console.info(v);
var displayLowercase = angular.lowercase(v.name);
return (displayLowercase.indexOf(lowercaseQuery) > -1);
};
};
function loadAll(query) {
AutocompleteSearch.get(query).success(function(data) {
var loadItems = [];
for(var i=0; i<data.deals.length; i++) {
data.deals[i].name += " (Neg贸cio)";
loadItems.push(data.deals[i]);
}
for(var i=0; i<data.organizations.length; i++) {
data.organizations[i].name += " (Organiza莽茫o)";
loadItems.push(data.organizations[i]);
}
for(var i=0; i<data.contacts.length; i++) {
data.contacts[i].name += " (Contato)";
loadItems.push(data.contacts[i]);
}
$scope.results = loadItems;
});
};
$scope.displaySearchedResult = function(result) {
if(result) {
var object_id = result._id;
var type = result.type;
if(type == "deal") {
$location.path("/deals/" + object_id);
} else if(type == "organization") {
$location.path("/organizations/" + object_id);
} else if(type == "contact") {
$location.path("/contacts/" + object_id);
}
}
};
}]);
@kykocamp try removing the "md-search-text-change" attribute. You already have the "md-items" directive fetching the results.
Also, if this doesn't solve the problem, please create a codepen.
@rcevs It didn't work actually. I took it off, ok! Less code, but the component acts the same way as before.
Like I said, already tried everything. I took this http://nikhilpatil.com/angularmaterialize_ajax_autocomplete.html as example to make my autocomplete request. And his example acts the same way. If you open his console, you'll see that sometimes the request is made, with results, and the dropdown doesn't update its content.
Your querySearch function must return the $http promise (not only the response). Please check this CodePen.
I've recently figured out 2 things I was doing wrong that led me here.
query function should be used in md-items and no other directives
md-items="item in query()"
as @rcevs pointed out, your query function should return the promise from $http
return $http( { url: '/foo/bar', method: 'POST', data: JSON.stringify({}) })
.then(response => {
return response.data;
})
.catch(err => {
return []; // { error: { source: "foo/bar/post" }, err: err };
});
The title of this bug matches my case but my details are a bit different. I think in the above cases if you set the no-cache=true
and setup the $http
response correctly it will work. However, after my http response my field is populated, but is only displayed after i click the md-autocomplete
field. Anybody know how i can either:
1) make the autocomplete fire without a click or
2) click the field forcing the select?
I am binding my form model field to this md-autocomplete
:
<div class="col-sm-9" ng-controller="InsurerCtrl as ctrl" layout="column" ng-cloak>
<md-content class="md-padding">
<form ng-submit="$event.preventDefault()">
<md-autocomplete md-autofocus="true"
ng-disabled="ctrl.isDisabled"
md-no-cache="true"
md-selected-item="ctrl.selectedItem"
md-search-text-change="ctrl.searchTextChange(ctrl.searchText)"
md-search-text="ctrl.searchText"
md-selected-item-change="ctrl.selectedItemChange(item)"
md-select-on-match="true"
md-match-case-insensitive="true"
md-items="item in ctrl.querySearch(ctrl.searchText)"
md-item-text="item.display"
md-min-length="0"
placeholder="Enter Insurer Name">
<md-item-template class="form-control">
<span md-highlight-text="ctrl.searchText" id="inputPrimaryIns" ng-bind="patient.primary_insurer.name" ng-init="ctrl.searchText=patient.primary_insurer">{{item.display}}</span>
</md-item-template>
<md-not-found>
"{{ctrl.searchText}}" not found.
<a ng-click="ctrl.newInsurer()">Create new!</a>
</md-not-found>
</md-autocomplete>
</form>
</md-content>
</div>
@rainabba Thank you, your suggestion solved my problem.
I'm having the same problem as @brandonwbrown - did you or anyone found a solution?
@salkz i ended up figuring it out. i needed to add setSelectedItem
to the .then
of the promise. it looks like this. hope it helps you:
if(id){
djangoAuth.request({url: "/patient-api/"+id[1]})
.then(function(data){
// success case
$scope.patient = data.data;
setSelectedItem($scope.patient.primary_insurer);
setSelectedItem2($scope.patient.secondary_insurer);
},function(data){
// error case
$scope.errors = data.data;
});
}else{ // create new patient case
$scope.patient = new Object();
}
js
function setSelectedItem(value) {
$scope.transformedQueryResults.some(function(item) {
if (item.value == value) {
$scope.selectedItem = item;
$scope.searchText = item.lowercase;
primary_insurer = item.value;
return true;
}
});
$log.info('Selected item changed to ' + JSON.stringify($scope.selectedItem));
}
@rcevs Thanks for the solution, works like charm. Saved my day !
The advice from https://github.com/angular/material/issues/6554#issuecomment-267738012 seems to be in the Basic Usage example of the autocomplete docs now.
There is no CodePen demo in the OP, so I can't really verify that any specific bug was fixed here. But it appears that the OP solved his issue and that many others have solved similar issues. I'm going to go ahead and close this.
If you run into some problems figuring out how to make this work, please post a question on the AngularJS Material forums. If you find a verifiable bug in autocomplete, please search for existing issues and if one can't be found please open a new issue using the issue template and providing a CodePen demo.
Thank you so much to the community for helping each other solve these!
Most helpful comment
Having the same issue. autocomplete list only updates for the previous query. ie- if i have a min character limit before query of 3, and i type 'cli' nothing happens. and when i type 'clin' it returns a list of results for 'cli'. the response from nominatum is obviously coming in after the list updates, but not sure how to fix this. js and html below. help would be much appreciated as i have been banging my head on the wall with this for ages.