From c718370e52cf8ecccb7d0183d69fb7dae7b88e1a Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Tue, 2 Feb 2016 18:06:33 +0100 Subject: [PATCH] fix(autocomplete): stop loading if last promise got resolved > Just investigated a bit, the problem is, the autocomplete will set the loading state to false if a previous promise is resolved. So when you search for A-R-I-Z-O-N-A (normally typed - not pasted) there will be a promise for each char. So the state of setLoading will change to false. This can be solved by adding a simple fetching queue. But only check the queue on the promise finally to store the retrieved results in cache. Fixes #6907 Closes #6927 # Conflicts: # src/components/autocomplete/js/autocompleteController.js --- .../autocomplete/js/autocompleteController.js | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/components/autocomplete/js/autocompleteController.js b/src/components/autocomplete/js/autocompleteController.js index 85ceee35668..194f9845186 100644 --- a/src/components/autocomplete/js/autocompleteController.js +++ b/src/components/autocomplete/js/autocompleteController.js @@ -19,7 +19,7 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, selectedItemWatchers = [], hasFocus = false, lastCount = 0, - promiseFetch = false; + fetchesInProgress = 0; //-- public variables with handlers defineProperty('hidden', handleHiddenChange, true); @@ -164,8 +164,8 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, */ function configureWatchers () { var wait = parseInt($scope.delay, 10) || 0; - $attrs.$observe('disabled', function (value) { ctrl.isDisabled = !!value; }); - $attrs.$observe('required', function (value) { ctrl.isRequired = !!value; }); + $attrs.$observe('disabled', function (value) { ctrl.isDisabled = $mdUtil.parseAttributeBoolean(value, false); }); + $attrs.$observe('required', function (value) { ctrl.isRequired = $mdUtil.parseAttributeBoolean(value, false); }); $scope.$watch('searchText', wait ? $mdUtil.debounce(handleSearchText, wait) : handleSearchText); $scope.$watch('selectedItem', selectedItemChange); angular.element($window).on('resize', positionDropdown); @@ -638,21 +638,30 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, */ function fetchResults (searchText) { var items = $scope.$parent.$eval(itemExpr), - term = searchText.toLowerCase(); - if (angular.isArray(items)) { - handleResults(items); - } else if (items) { + term = searchText.toLowerCase(), + isList = angular.isArray(items); + + if ( isList ) handleResults(items); + else handleAsyncResults(items); + + function handleAsyncResults(items) { + if ( !items ) return; + + items = $q.when(items); + fetchesInProgress++; setLoading(true); - promiseFetch = true; + $mdUtil.nextTick(function () { - if (items.success) items.success(handleResults); - if (items.then) items.then(handleResults); - if (items.finally) items.finally(function () { - setLoading(false); - promiseFetch = false; - }); + items + .then(handleResults) + .finally(function(){ + if (--fetchesInProgress === 0) { + setLoading(false); + } + }); },true, $scope); } + function handleResults (matches) { cache[ term ] = matches; if ((searchText || '') !== ($scope.searchText || '')) return; //-- just cache the results if old request @@ -707,6 +716,10 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, } } + function isPromiseFetching() { + return fetchesInProgress !== 0; + } + function scrollTo (offset) { elements.$.scrollContainer.controller('mdVirtualRepeatContainer').scrollTo(offset); } @@ -714,7 +727,7 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, function notFoundVisible () { var textLength = (ctrl.scope.searchText || '').length; - return ctrl.hasNotFound && !hasMatches() && (!ctrl.loading || promiseFetch) && textLength >= getMinLength() && (hasFocus || noBlur) && !hasSelection(); + return ctrl.hasNotFound && !hasMatches() && (!ctrl.loading || isPromiseFetching()) && textLength >= getMinLength() && (hasFocus || noBlur) && !hasSelection(); } /** @@ -745,7 +758,12 @@ function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, matches = ctrl.matches, item = matches[ 0 ]; if (matches.length === 1) getDisplayValue(item).then(function (displayValue) { - if (searchText == displayValue) select(0); + var isMatching = searchText == displayValue; + if ($scope.matchInsensitive && !isMatching) { + isMatching = searchText.toLowerCase() == displayValue.toLowerCase(); + } + + if (isMatching) select(0); }); }