我正在尝试将一个承诺绑定到一个视图。我不知道你是否可以直接这样做,但这就是我想要做的。我有什么想法吗?
注意:使用超时并使用静态数据时,源代码有点做作,但这样可以使代码更易于诊断。
编辑: JSFiddle页面:http://jsfiddle.net/YQwaf/27/
编辑:解决方案结果证明你可以直接绑定promises。我的原始代码有两个问题:
HTML:
<div ng:controller="addressValidationController">
Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in getRegions()"/>
Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>
JS:
function addressValidationController($scope, $q) {
var regions = {
US: [{code: 'WI',name: 'Wisconsin'}, {code: 'MN',name: 'Minnesota'}],
CA: [{code: 'ON',name: 'Ontario'}]
};
$scope.getRegions = function () {
var deferred = $q.defer();
setTimeout(function () {
var countryRegions = regions[$scope.countryCode];
console.log(countryRegions);
if(countryRegions === undefined) {
deferred.resolve([]);
} else {
deferred.resolve(countryRegions);
}
}, 1000);
return deferred.promise;
};
}
答案 0 :(得分:71)
从Angular 1.2开始,you can't use promises in templates directly anymore
相反,您需要将结果放入$scope
then
内,就像通常那样 - 没有魔力。
作为获取旧行为的临时解决方法,您可以调用
$parseProvider.unwrapPromises(true)
但稍后会删除此功能,因此请不要依赖它。
答案 1 :(得分:29)
警告:这个答案在编写时是准确的,但从1.2开始,Angular模板引擎无法透明地处理承诺! - @Malvolio
是的,模板引擎(和表达式)透明地处理promises,但我会将promise分配给控制器中的scope属性,而不是每次都调用一个返回新promise的函数(我认为这是你的问题,已解决的承诺丢失了因为每次都会返回一个新的承诺。
JSFiddle:http://jsfiddle.net/YQwaf/36/
HTML:
<div ng:controller="addressValidationController">
Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in regions"/>
Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>
JS:
function addressValidationController($scope, $q, $timeout) {
var regions = {
US: [{
code: 'WI',
name: 'Wisconsin'},
{
code: 'MN',
name: 'Minnesota'}],
CA: [{
code: 'ON',
name: 'Ontario'}]
};
function getRegions(countryCode) {
console.log('getRegions: ' + countryCode);
var deferred = $q.defer();
$timeout(function() {
var countryRegions = regions[countryCode];
if (countryRegions === undefined) {
console.log('resolve empty');
deferred.resolve([]);
} else {
console.log('resolve');
deferred.resolve(countryRegions);
}
}, 1000);
return deferred.promise;
};
$scope.regions = [];
// Manage country changes:
$scope.$watch('countryCode', function(countryCode) {
if (angular.isDefined(countryCode)) {
$scope.regions = getRegions(countryCode);
}
else {
$scope.regions = [];
}
});
}
答案 2 :(得分:27)
从Angular 1.3开始 - $parseProvider.unwrapPromises(true)
will no longer work。
相反,你应该直接解开承诺:
myApiMethod().then(function(value){
$scope.item = value;
});
请注意,承诺展开仍然可以照常使用ngResource。
答案 3 :(得分:0)
返回对包含列表的范围变量的引用应该足够了。
function addressValidationController($scope,$timeout) {
var regions = {
US: [{code: 'WI',name: 'Wisconsin'}, {code: 'MN',name: 'Minnesota'}],
CA: [{code: 'ON',name: 'Ontario'}]
};
$scope._regions = [];
$scope.getRegions = function () {
$timeout(function () {
var countryRegions = regions[$scope.countryCode];
console.log(countryRegions);
if(countryRegions === undefined) {
$scope._regions = []
} else {
$scope._regions = countryRegions
}
}, 1000);
return $scope._regions;
};
}