AngularJS promise
Asked Answered
L

3

10

AngularJS docs say:

$q promises are recognized by the templating engine in angular, which means that in templates you can treat promises attached to a scope as if they were the resulting values.

So could someone please explain the reason this fiddle not working? It's not possible to change text field value. But assigning promises that $http service returns to a scope field works like a charm.

Controller:

function MyController($scope, $q, $timeout) {
    this.getItem = function () {
        var deferred = $q.defer();
        deferred.resolve({
            title: 'Some title'
        });
        return deferred.promise;
    };

    $scope.item = this.getItem();
}

Html:

<input type="text" ng-model="item.title">
Lettie answered 29/12, 2012 at 8:44 Comment(4)
Could you show me how you assigned a promise returned by $http which worked the way you wanted?After
@Dogbert, Here is pseudocode to illustrate what I was talking about: $scope.item = $http({method: 'post', url: '/find/my/item/'}) .then(function (response) { return response.item; }); Another example that uses $resource approach can be found in this tutorial. Starting from the line: Notice how in PhoneListCtrl we replaced ... with $scope.phones = Phone.query();Vespasian
Oops, just created test example, and it appears not to work with any promiseVespasian
Hey guys, to get it to work, I had to use .success(function(){}).then(function(r){if (r.data["my-result"])return r.data["my-result"];});Liatrice
M
14

You need to use the then() function on the promise object:

this.getItem().then(function(result) {
   $scope.item = result;
});

In your case I don't think you need a promise. Angular's $watch system will take care of things. Just return an object in your function, not a primitive type:

this.getItem = function () {
    var item = {};

    // do some async stuff
    $http.get(...).success(function(result) {
       item.title = result;
    });
    return item;
};

$scope.item = this.getItem();
Mccormack answered 29/12, 2012 at 10:31 Comment(4)
I know what you mean. I've updated my answer. You have to let angular take care of it (it will do it automatically with its $watch system).Mccormack
The second example you gave doesn't look simpler than the first one ;) Besides, it's not going to work as expected, because $http.get() will be resolved with json representing item , not just title So this.getItem().then(function(result) { $scope.item = result; }); looks quite acceptable (I just changed this.item = result to $scope.item = result)Vespasian
Ah, indeed that this should have been scope. I'll change it so you can accept it.Mccormack
I'm not sure this addresses the fact that AngularJS claims promises can be used during binding as though they were the result... The docs still say that and I'd like to know why his code didn't work. Perhaps it only works if the deferred resolves after the template has finished digesting? It's not typical to resolve synchronously before returning the promise.Stifle
M
1

I believe the reason your first fiddle does not work is because you are essentially binding scope property item to a promise. When you attempt to alter the value by typing into the text field, angular notices the activity, and then reassigns/resets the value of item to the result of the promise (which hasn't changed).

The solution provided by @asgoth sets/assigns the value of item once, when the promise is resolved. There is no binding going on here (i.e, item is not bound to the promise), so altering the value via the textbox does alter the value.

Merete answered 29/12, 2012 at 18:7 Comment(0)
B
-1

Its like @Mark said, here you can find a Working Example of your snippet.

Basically you were returning an object and not binding the model itself.

$timeout(function(){
   $scope.item = {
      title: 'Some title'
   }; // Apply the binding
   deferred.resolve(); // Resolve promise
},2000); // wait 2 secs           
Bus answered 29/12, 2012 at 19:36 Comment(1)
The last line of your JavaScript should probably simply be this.getItem();.Merete

© 2022 - 2024 — McMap. All rights reserved.