In version 1.0.7 I get this error when typing in md-autocomplete
:
angular.js:13550 TypeError: Cannot read property 'then' of undefined
The error seems NOT to happen in a previous version. More detailed explanation is on StackOverflow.
Upgrade to 1.1.0-rc4.
I am also getting this, upgrade to 1.1.0-rc4 did not fix it.
I had the same error caused by following query function:
function querySearch(searchText) {
if (!searchText)
return;
...
}
The fix was to return an empty array in case of an empty searchText.
@berkyl You are right! Thank you!
I'm getting a similar thing in 1.1.0-rc5 even when there is a searchText
it seems like it can't eval md-items="item in userSearch(searchHelpers.query)"
scope.userSearch = function (query) {
if (scope.contactMap) {
var results = query ? scope.contactMap.filter(createFilterFor(query)) : [];
return results;
}
};
That's a f ridiculous issue: isPromise = items && items.then;
It makes me reconsider the experience of people I'm trusting on.
This issue is first in google ( "angular autocomplete Cannot read property 'then' of undefined" ). I think it may help some people:
This error occures also when you use function that does not exist, like:
md-items="item in notExistingFunction(query)"
and there is no other information in error stack (angular digest.. and then 'cannot read prop...').
@marcioaso
https://material.angularjs.org/latest/api/directive/mdAutocomplete
- md-items expression
An expression in the format of item in items to iterate over matches for your search.
!!items.then - items must be defined, as every variable over which you can iterate
Checking if items exists would be an issue - waste of CPU (I'm not sure about it) and code not according to documentation.
I came across this problem as well, and managed to fix it. For future references you can check out my snippet (excuse the Dutch comments): http://pastebin.com/HtXgz5DC
version : 1.1.1
Hi got the same issue, and trying what u guys told didn't work for me..
Here is my component :
angular.module('searchbar').component('searchbar', {
templateUrl: 'dist/search/template/search.html',
controller: [
'$scope',
'$http',
'$q',
'$log',
function autoCompleteController($scope, $http, $q, $log) {
var self = this;
self.queryResults = getResults().then(function(response) {
return response.data;
});
console.log(self.queryResults);
self.querySearch = querySearch;
self.selectedItemChange = selectedItemChange;
self.searchTextChange = searchTextChange;
function querySearch(query) {
var results = query ? self.queryResults : [];
return $q.when(results);
}
function searchTextChange(text) {
$log.info('Text changed to ' + text);
}
function selectedItemChange(item) {
$log.info('Item changed to ' + JSON.stringify(item));
}
function getResults() {
return $http.get('data/searchResults.json');
}
}
]
}).controller('autoCompleteController', function($scope) {
});
Here is my template/search.html
:
<div id="searchBar" ng-controller="autoCompleteController as ctrl" layout="column" ng-cloak>
<md-content>
<form ng-submit="$event.preventDefault()">
<md-autocomplete
md-no-cache="ctrl.noCache"
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-items="item in ctrl.querySearch(ctrl.searchText)"
md-item-text="item.display"
md-min-length="0"
placeholder="Search..."
>
<md-item-template>
<span class="item-title">
<!-- <md-icon aria-label="account-circle" class="material-icons">
view_modules
</md-icon> -->
<span> {{$ctrl.item.name}} </span>
</span>
</md-item-template>
<md-not-found>
Aucun r茅sultat correspondant 脿 "{{ctrl.searchText}}" n'a 茅t茅 trouv茅.
</md-not-found>
</md-autocomplete>
</form>
</md-content>
</div>
Can someone tell me how to solve this issue ?
hello,
i have same problem than @KGALLET
Version: 1.1.1
@fx69005: It's probably because your self.queryResults
is not well instantiated. I mean, the promise I made is not well done.
BTW, I managed to solve my problem. I can close so.
(function() {
angular
.module('searchbar', ['ngMaterial'])
.controller('SearchBar', SearchBar);
function SearchBar($http) {
var self = this;
self.queryResults = [];
self.transformedQueryResults = transformResults();
self.querySearch = querySearch;
self.selectedItemChange = selectedItemChange;
function getResults() { return $http.get('data/searchResults.json'); }
function querySearch (query) {
var results = query ? self.transformedQueryResults.filter(createFilterFor(query)) : self.transformedQueryResults;
console.log(self.queryResults);
return results;
}
function selectedItemChange(item) {
console.log(item);
}
function transformResults() {
getResults().then(function(response){
var transformedResults = [];
var results = response.data;
results.forEach(function(item) {
var transformedItem = parseItem(item);
transformedResults.push(transformedItem);
});
// queryResults get the items with all the informations, it is usefull
// for the implementation of the selectedItemChange method (send mail, call number.. etc)
self.queryResults = results;
// here, only the objects i want to save
self.transformedQueryResults = transformedResults;
});
}
// the value is important to filter the results
function parseItem(item) {
switch(item.type) {
// case 'software':
// return {
// "display" : item.infos.name,
// "value": angular.lowercase(item.infos.name),
// "icon" : item.infos.icon,
// }
// break;
// case 'customer':
// return {
// "display" : item.infos.name,
// "value": angular.lowercase(item.infos.name),
// "icon" : item.infos.icon,
// }
// break;
case 'contributor':
return {
"display" : item.infos.company + ', ' + item.infos.name,
"value": angular.lowercase(item.infos.company + ', ' + item.infos.name),
"icon" : item.infos.icon,
}
break;
default:
return {
"display" : item.infos.name,
"value": angular.lowercase(item.infos.name),
"icon" : item.infos.icon,
}
break;
}
}
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(state) {
console.log(state.display);
return (state.value.indexOf(lowercaseQuery) === 0);
};
}
}
})();
Hi,
I had the same problem. In my case it was caused by querySearch.
In the view I had :
md-items="item in ctrl.querySearch(ctrl.searchText)"
I changed it to :
md-items="item in querySearch(ctrl.searchText)"
That's fixed the issue
it's really ridicule to have this kind of bug from google, 馃憥
how can fix that
It's not a bug. The search function should return a promise before it can resolve the async result from your function - assuming you do a async request to the server (read about promises here: https://docs.angularjs.org/api/ng/service/$q
One example how you can solve it (not a working example but here is the gist of it):
app.controller('TestCtrl', function($q, MySearchService) {
// handle undefined input (e.g. return empty array)
if (typeof searchText != 'undefined') {
$scope.search = function(searchText) {
deferred = $q.defer();
MySearchService.searchText(searchText).then(function(resp) {
// parse results to list
deferred.resolve(resp.mylist);
}).catch(function(err) {
console.log(err);
});
return deferred.promise;
}
} else {
return [];
}
});
I solved this issue in my code by returning the http object in the search function:
$scope.getMapsMatches = function(searchText) {
return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: searchText
}
})
.then(function(response) { ....
I added self.states = [] before calling the query and the error disappeared from console
Two options, which worked for me:
1) md-min-length="0" -> make it more than 0
2) if you want to keep 0, make sure to return empty array, when nothing is found in search method, so instead of:
var results = query ? scope.contactMap.filter(createFilterFor(query)) : [];
return results;
do more like:
var results = query ? scope.contactMap.filter(createFilterFor(query)) : [];
return results ? results : [];
Most helpful comment
That's a f ridiculous issue:
isPromise = items && items.then;
It makes me reconsider the experience of people I'm trusting on.