Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular JS: how to bind to promises

I am trying to bind a promise to a view. I don't know if you can do that directly, but that's what I'm attempting to do. Any ideas what I am doing wrong?

Note: the source is a little contrived with the timeout and uses static data, but that's to make the code easier to diagnose.

EDIT: JSFiddle Page: http://jsfiddle.net/YQwaf/27/

EDIT: SOLUTION: It turned out you can directly bind promises. I had two problems with my original code:

  1. Using setTimeout() instead of angular's $timeout was a problem. Angular doesn't know it needs to refresh the UI when the timeout is triggered ( You could solve this with $scope.$apply inside setTimeout, or you can just use $timeout )
  2. Binding to a function that returned a promise was a problem. If it gets called a second time, it makes yet another promise. Better is to set a scope variable to the promise and only create a new promise as needed. (In my case, this was calling $scope.$watch on the Country Code)

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;     }; } 
like image 427
Adam Tegen Avatar asked Oct 23 '12 14:10

Adam Tegen


1 Answers

As of Angular 1.2, you can't use promises in templates directly anymore.
Instead, you need to put the result into $scope inside then, like you normally would—no magic.

As a temporary workaround to get the old behavior, you can call

$parseProvider.unwrapPromises(true) 

but this feature will be removed later on, so don't depend on it.

like image 99
Dan Abramov Avatar answered Sep 19 '22 23:09

Dan Abramov