$http 问题 - 在 md-autocomplete Angular Material 中解决承诺之前无法返回值 [英] $http issue - Values can't be returned before a promise is resolved in md-autocomplete Angular Material
问题描述
我在我的项目中使用 Angular Material md-autocomplete
.因为我使用 $http
服务通过 ajax 调用从服务主机获取建议列表.
问题:$http 问题 - 在承诺生效之前无法返回值在 md-autocomplete
Angular Material
我的要求:我需要使用远程数据更新的建议列表md-autocomplete
Angular Material - Ajax $http
服务中的源.
我使用了 Angular Material 链接中提到的方法
这里我正在搜索 indian,但它显示了 india 的结果.我在 Firefox Browser Firebug 中调试了该问题,请参阅上面显示的 Snapshot 1,请求是通过 POST 方法针对搜索词 indian 发送的我成功地得到了一个匹配项作为 JSON 对象的响应,显示在 SnapShot 1
的底部<块引用>我在这种情况下发现的问题,之前无法返回值承诺已解决
我尝试的步骤:
案例 1:我在 UI md-items="item in Person | filter: searchText"
中使用了 AngularJS filter
,它给出先前获取的远程数据的过滤列表,而不是当前获取的远程数据.在退格文本框中的字符时,它显示不正确的建议列表.
案例 2:我尝试通过在 $http
服务中调用 $scope.$apply()
来更新 UI 中的更改,但它失败了.因为 $http
服务默认调用 $scope.$apply()
,显示它会抛出一个错误 Error: [$rootScope:inprog]....最终在这次尝试中我失败了.
案例 3:我创建了一个函数,在该函数中我手动调用了 $scope.$apply()
,在我手动推送和弹出的函数中$scope
变量的一个虚拟项目,该变量绑定在 md-autocomplete
中.但我在这次尝试中失败了.因为在这里我也得到了与快照相同的输出.
function Ctrlm($scope) {$scope.messageToUser = "你完成了!";设置超时(函数(){$scope.$apply(function () {$scope.dummyCntry = [{斯诺:0,国家: ""},];$scope.Person.push($scope.dummyCntry);var index = $scope.Person.indexOf($scope.dummyCntry);$scope.Person.splice(index, 1);});}, 10);}
案例 4:我在 $scope.$watchCollection 中采用了与案例 3"相同的方法.在这里,我也遇到了挫折.
$scope.$watchCollection('Person', function (newData, oldData) {$scope.dummyCntry = [{斯诺:0,国家: ""},];newData.push($scope.dummyCntry);var index = newData.indexOf($scope.dummyCntry);newData.splice(index, 1);});
案例 5:我没有使用 $http
服务,而是使用了 jquery ajax 调用.我使用 $scope.apply()
手动更新 UI.我在这次尝试中再次失败了,在这里我也得到了相同的输出.
$scope.searchTextChange = function () {if (($scope.searchText != undefined) && ($scope.searchText != null)) {$.ajax({类型:'获取',url: "https://www.bbminfo.com/sample.php?token=" + $scope.searchText,成功:功能(响应){$scope.$apply(function () {$scope.Person = response.records;});},错误:函数(数据){$scope.$apply(function () {$scope.Person = [];});},异步:真});} 别的 {$scope.Person = [];}}
<块引用>
在所有尝试中我都无法解决问题.
@georgeawg https://stackoverflow.com/users/5535245/georgeawg 建议我发布一个新问题,他说:写一个新问题,描述您实际尝试完成的工作,包括所需的行为、迄今为止您为解决问题所做的工作的总结,以及您遇到的困难的描述正在解决它."
我之前发布的参考问题
<块引用>我的要求:我需要使用远程数据更新的建议列表Angular Material md-autocomplete
- Ajax $http
服务中的源.
请在这方面帮助我.
<块引用>出于测试目的使用以下源代码
对远程数据源使用以下 URL:https://bbminfo.com/sample.php?token=ind
远程数据源 URL 包含国家/地区名称列表.
<块引用>通过单击下面的运行代码片段按钮直接测试代码.
完整的 HTML 与 AngularJS 源代码:
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css"><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script><!-- 角度材料库--><script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.js"></script><身体><div ng-app="myApp" ng-controller="myCtrl"><p>要选择的国家/地区:</p><md-内容><md-自动完成ng-disabled="isDisabled"md-no-cache="noCache"md-selected-item="selectedItem"md-search-text-change="searchTextChange()"md-search-text="searchText"md-selected-item-change="selectedItemChange(item)"md-items="个人物品"md-item-text="item.country"md-min-length="0"placeholder="你最喜欢哪个国家?"><md-item-模板><span md-highlight-text="searchText" md-highlight-flags="^i">{{item.country}}</span></md-item-template><md-not-found>未找到匹配{{searchText}}"的人员.</md-not-found></md-自动完成></md-content><br/>
<脚本>var app = angular.module('myApp', ['ngMaterial']);app.controller('myCtrl', function ($scope, $http, $q) {$scope.searchText = "";$scope.Person = [];$scope.selectedItem = [];$scope.isDisabled = false;$scope.noCache = false;$scope.selectedItemChange = 函数(项目){alert("物品已更改");}$scope.searchTextChange = 函数 () {$http({方法:发布",url: "https://www.bbminfo.com/sample.php",参数:{令牌:$scope.searchText}}).成功(功能(响应){$scope.Person = response.records;});}});</html>
@KevinB https://stackoverflow.com/users/400654/kevin-b - 给出了如何实施的想法.我真的很感谢他...再次感谢凯文...
我得到了我需要的确切解决方案.
源代码是
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css"><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script><script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script><!-- 角度材料库--><script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.4/angular-material.min.js"></script><身体><div ng-app="myApp" ng-controller="myCtrl"><p>要选择的国家/地区:</p><md-内容><md-自动完成ng-disabled="isDisabled"md-no-cache="noCache"md-selected-item="selectedItem"md-search-text="searchText"md-items="searchTextChange(searchText) 中的项目"md-item-text="item.country"md-min-length="0"placeholder="你最喜欢哪个国家?"><md-item-模板><span md-highlight-text="searchText" md-highlight-flags="^i">{{item.country}}</span></md-item-template><md-not-found>未找到匹配{{searchText}}"的人员.</md-not-found></md-自动完成></md-content><br/>
<脚本>var app = angular.module('myApp', ['ngMaterial']);app.controller('myCtrl', function ($scope, $http, $q, GetCountryService) {$scope.searchText = "";$scope.Person = [];$scope.selectedItem = [];$scope.isDisabled = false;$scope.noCache = false;$scope.selectedItemChange = 函数(项目){//警报(项目已更改");}$scope.searchTextChange = 函数 (str) {返回 GetCountryService.getCountry(str);}});app.factory('GetCountryService', function ($http, $q) {返回 {getCountry:函数(str){//$http API 基于 $q 服务公开的延迟/承诺 API//所以它默认为我们返回一个promisevar url = "https://www.bbminfo.com/sample.php?token="+str;返回 $http.get(url).then(功能(响应){if (typeof response.data.records === 'object') {返回 response.data.records;} 别的 {//无效响应返回 $q.reject(response.data.records);}},功能(响应){//出了些问题返回 $q.reject(response.data.records);});}};});</html>
我在以下博客中简要介绍了 md-autocomplete - http://www.increvcorp.com/usage-of-md-autocomplete-in-angular-material/
I'm using Angular Material md-autocomplete
in my project. In that I'm getting the suggest listing from the Service Host via ajax call using $http
service.
Issue: $http issue - Values can't be returned before a promise is resolved in
md-autocomplete
Angular MaterialMy Requirement: I need an updated Suggestion List using remote data sources in
md-autocomplete
Angular Material - Ajax$http
service.
I used the approach as mentioned in Angular Material link https://material.angularjs.org/latest/demo/autocomplete
Source Code:
Scenario 1:
HTML Source Code:
<md-autocomplete flex required
md-input-name="autocompleteField"
md-no-cache="true"
md-input-minlength="3"
md-input-maxlength="18"
md-selected-item="SelectedItem"
md-search-text="searchText"
md-items="item in querySearch(searchText)"
md-item-text="item.country" Placeholder="Enter ID" style="height:38px !important;">
<md-item-template>
<span class="item-title">
<span md-highlight-text="searchText" md-highlight-flags="^i"> {{item.country}} </span>
</md-item-template>
</md-autocomplete>
AngularJS Script:
//bind the autocomplete list when text change
function querySearch(query) {
var results = [];
$scope.searchText = $scope.searchText.trim();
if (query.length >=3) {
results = LoadAutocomplete(query);
}
return results;
}
//load the list from the service call
function LoadAutocomplete(id) {
var countryList = [];
$http({
method: "post",
url: "https://www.bbminfo.com/sample.php",
params: {
token: id
}
})
.success(function (response) {
countryList = response.records;
});
return countryList;
}
Scenario 2:
HTML with AngularJS Source Code:
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script>
<!-- Angular Material Library -->
<script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p>Person to Select:</p>
<md-autocomplete
ng-disabled="isDisabled"
md-no-cache="noCache"
md-selected-item="selectedItem"
md-search-text-change="searchTextChange()"
md-search-text="searchText"
md-selected-item-change="selectedItemChange(item)"
md-items="item in Person"
md-item-text="item.Name"
md-min-length="0"
placeholder="Which is your favorite Person?">
<md-item-template>
<span md-highlight-text="ctrl.searchText" md-highlight-flags="^i">{{item.country}}</span>
</md-item-template>
<md-not-found>
No Person matching "{{searchText}}" were found.
</md-not-found>
</md-autocomplete>
<br/>
</div>
<script>
var app = angular.module('myApp', ['ngMaterial']);
app.controller('myCtrl', function ($scope, $http, $q) {
$scope.searchText = "";
$scope.Person = [];
$scope.selectedItem = [];
$scope.isDisabled = false;
$scope.noCache = false;
$scope.selectedItemChange = function (item) {
alert("Item Changed");
}
$scope.searchTextChange = function () {
$http({
method: "POST",
url: "https://www.bbminfo.com/sample.php",
params: {
token: $scope.searchText
}
})
.success(function (response) {
$scope.Person = response.records;
});
}
});
</script>
</body>
</html>
In Scenario 1, I used the function to fetch the filtered list md-items="item in querySearch(searchText)"
. But in Scenario 2, I used a $scope
variable md-items="item in Person"
Kindly refer the Snapshots
Snapshot 1:
Here I'm searching for indian but it shows the result for india. I debugged the issue in Firefox Browser Firebug, see the above Snapshot 1 it shows, the request was sent for the search term indian via POST Method and I got the response of one matching items as a JSON Object successfully, which is shown in the bottom of SnapShot 1
The issue I find out in this case, the Values can't be returned before a promise is resolved
Steps I tried:
Case 1: I used the AngularJS filter
in UI md-items="item in Person | filter: searchText"
, it gives the filtered list of previously fetched remote data not a currently fetched remote data. While on Backspacing the character in the textbox it shows the improper suggestion list.
Case 2: I tried to update the changes in UI by calling $scope.$apply()
within a $http
service, but it fails. Because $http
service calling the $scope.$apply()
by default, show it throws me an error Error: [$rootScope:inprog].... Finally in this attempt I failed.
Case 3: I created a function, within the function I'm manually called the $scope.$apply()
, within the function I manually pushed and poped one dummy item to the $scope
variable which is bind in the md-autocomplete
. But I failed in this attempt. Because here also I got a same output as same as in the snapshot.
function Ctrlm($scope) {
$scope.messageToUser = "You are done!";
setTimeout(function () {
$scope.$apply(function () {
$scope.dummyCntry = [
{
sno: 0,
country: ""
},
];
$scope.Person.push($scope.dummyCntry);
var index = $scope.Person.indexOf($scope.dummyCntry);
$scope.Person.splice(index, 1);
});
}, 10);
}
Case 4: I did the same approach as like "Case 3" within the $scope.$watchCollection. Here also I got a setback.
$scope.$watchCollection('Person', function (newData, oldDaata) {
$scope.dummyCntry = [
{
sno: 0,
country: ""
},
];
newData.push($scope.dummyCntry);
var index = newData.indexOf($scope.dummyCntry);
newData.splice(index, 1);
});
Case 5: Instead of $http
service, I used the jquery ajax call. In that I used the $scope.apply()
to update the UI manually. I failed in this attempt once again, here also I got the same output.
$scope.searchTextChange = function () {
if (($scope.searchText != undefined) && ($scope.searchText != null)) {
$.ajax({
type: 'GET',
url: "https://www.bbminfo.com/sample.php?token=" + $scope.searchText,
success: function (response) {
$scope.$apply(function () {
$scope.Person = response.records;
});
},
error: function (data) {
$scope.$apply(function () {
$scope.Person = [];
});
},
async: true
});
} else {
$scope.Person = [];
}
}
In all the attempts I can't able to fix the issue.
@georgeawg https://stackoverflow.com/users/5535245/georgeawg suggested me to post a new question, he stated, "write a new question that describes what you are actually trying to accomplish, include the desired behavior, a summary of the work you've done so far to solve the problem, and a description of the difficulty you are having solving it."
Reference Questions which I was posted in the earlier
My Requirement: I need an updated Suggestion List using remote data sources in Angular Material
md-autocomplete
- Ajax$http
service.
Kindly assist me in this regards.
For Testing Purpose Use the following Source Code
Use the following URL for Remote Data Source: https://bbminfo.com/sample.php?token=ind
The Remote Data Source URL contains the List of Countries Name.
Directly Test the Code by click the below Run Code Snippet button.
Complete HTML with AngularJS Source Code:
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script>
<!-- Angular Material Library -->
<script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p>Country to Select:</p>
<md-content>
<md-autocomplete
ng-disabled="isDisabled"
md-no-cache="noCache"
md-selected-item="selectedItem"
md-search-text-change="searchTextChange()"
md-search-text="searchText"
md-selected-item-change="selectedItemChange(item)"
md-items="item in Person"
md-item-text="item.country"
md-min-length="0"
placeholder="Which is your favorite Country?">
<md-item-template>
<span md-highlight-text="searchText" md-highlight-flags="^i">{{item.country}}</span>
</md-item-template>
<md-not-found>
No Person matching "{{searchText}}" were found.
</md-not-found>
</md-autocomplete>
</md-content>
<br/>
</div>
<script>
var app = angular.module('myApp', ['ngMaterial']);
app.controller('myCtrl', function ($scope, $http, $q) {
$scope.searchText = "";
$scope.Person = [];
$scope.selectedItem = [];
$scope.isDisabled = false;
$scope.noCache = false;
$scope.selectedItemChange = function (item) {
alert("Item Changed");
}
$scope.searchTextChange = function () {
$http({
method: "post",
url: "https://www.bbminfo.com/sample.php",
params: {
token: $scope.searchText
}
})
.success(function (response) {
$scope.Person = response.records;
});
}
});
</script>
</body>
</html>
@KevinB https://stackoverflow.com/users/400654/kevin-b - Gives the Idea how to implement. I really thank him... Once again thanks alot Kevin...
I got the Exact solution, what I need.
The Source Code is
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-aria.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-messages.min.js"></script>
<!-- Angular Material Library -->
<script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.0.4/angular-material.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p>Country to Select:</p>
<md-content>
<md-autocomplete
ng-disabled="isDisabled"
md-no-cache="noCache"
md-selected-item="selectedItem"
md-search-text="searchText"
md-items="item in searchTextChange(searchText)"
md-item-text="item.country"
md-min-length="0"
placeholder="Which is your favorite Country?">
<md-item-template>
<span md-highlight-text="searchText" md-highlight-flags="^i">{{item.country}}</span>
</md-item-template>
<md-not-found>
No Person matching "{{searchText}}" were found.
</md-not-found>
</md-autocomplete>
</md-content>
<br/>
</div>
<script>
var app = angular.module('myApp', ['ngMaterial']);
app.controller('myCtrl', function ($scope, $http, $q, GetCountryService) {
$scope.searchText = "";
$scope.Person = [];
$scope.selectedItem = [];
$scope.isDisabled = false;
$scope.noCache = false;
$scope.selectedItemChange = function (item) {
//alert("Item Changed");
}
$scope.searchTextChange = function (str) {
return GetCountryService.getCountry(str);
}
});
app.factory('GetCountryService', function ($http, $q) {
return {
getCountry: function(str) {
// the $http API is based on the deferred/promise APIs exposed by the $q service
// so it returns a promise for us by default
var url = "https://www.bbminfo.com/sample.php?token="+str;
return $http.get(url)
.then(function(response) {
if (typeof response.data.records === 'object') {
return response.data.records;
} else {
// invalid response
return $q.reject(response.data.records);
}
}, function(response) {
// something went wrong
return $q.reject(response.data.records);
});
}
};
});
</script>
</body>
</html>
I Briefly explained about md-autocomplete in the following blog - http://www.increvcorp.com/usage-of-md-autocomplete-in-angular-material/
这篇关于$http 问题 - 在 md-autocomplete Angular Material 中解决承诺之前无法返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!