Question

I am trying to remotely get a user's name and then have it editable so that it can be saved again. I am getting the name correctly, but when I try to change it, it reverts back to the old name.

Am I doing something wrong with the defer and resolve?

var deferred = $q.defer();
    $http({
            url : '/getuser',
            method : 'GET',
          }).success(function(data) {
             deferred.resolve(data);
          });
         return deferred.promise;

http://jsfiddle.net/NfPcH/181/

Was it helpful?

Solution

You're assigning the promise directly to your model variable. So even though in many ways your variable acts like it got the results of the promise it actually instead contains a binding to the promise.

So your variable keeps getting set to resolved value of the promise during $digest cycles - overwriting your edits.

So instead of binding your variable to the promise like this:

$scope.myUser = getUser();

Use the promise's then method and assign the results of the promise. This way myUser is initialized to the results of your promise just once instead of being perpetually bound to the promise itself.

getUser().then(function(result) {
     $scope.myUser = result;
});

OTHER TIPS

For this example, you don't really need to have an explicit promise. $http already returns a promise so you really don't need to define a new one.

I've re-arranged the code a bit. In order to initialize the value, I'm using ng-init to call the getUser() method. This then calls $http and binds to the $scope.myUser. BTW, I noticed that in only ever enters the error callback.

Because promises are async, you must bind to the $scope inside the success or error callback function of $http.

The reason it was reverting to the 'old' value was because you were binding directly to the function getUser(). This meant that angular was setting up a $watch on the return value of this function.

Here is a working fiddle.

HTML:

<h4>remote</h4>
<div ng-app="app" ng-controller="Ctrl" ng-init="init()">
  <a href="#" editable-text="myUser.name" >
    {{ myUser.name || 'not set!' }}
  </a>
</div>

JS:

app.controller('Ctrl', function($scope, $http, $q) {
    $scope.myUser = null;

    $scope.init = function() {

        getUser();
    };

    function getUser() {

            return $http({
                url : 'http://espn.com/images/test-data/public-profile.json',
                method : 'GET',
            })
            .error(function(data) {
                $scope.myUser = {"name":"bobby","age":"21"};
            })
            .success(function(data) {
                console.log(data);
                $scope.myUser = data;
            });

        };
}); 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top