user2936314
user2936314

Reputation: 1792

Angular 'controller as' updating an attribute inside a function

I'm trying to learn to use controller as more often in my angular controllers and ran into a scoping issue when updating a scope from inside another function:

.controller('profileCtrl', function(ProfileData, Restangular){
  // ProfileData comes from router.resolve

  this.user = ProfileData;

  // I want to update the data with a button click or something
  this.refresh = function(id){
    Restangular.one('users', id).get().then(function(resp){
      this.user = resp;
    })
  }
});

The this.user = resp doesn't actually refer to the same this in this.user = ProfileData. I don't know what it refers to, maybe the function?

I fixed this by injecting scope and then changing my update function:

  this.refresh = function(id){
    Restangular.one('users', id).get(params).then(function(resp){
      $scope.profile.user = resp;
    })
  }

The problem I have with this approach is that it depends on me calling the controller myCtrl as profile.

Is there a way to update this.user from within my function without injecting scope?

Upvotes: 2

Views: 69

Answers (2)

Jhecht
Jhecht

Reputation: 4435

You can always use function binding to help you out, but the problem with it is that you therefore lose access to any of the methods or values on what would be the default this. For example,

.controller('profileCtrl', function(ProfileData, Restangular){
  // ProfileData comes from router.resolve

  this.user = ProfileData;

  // I want to update the data with a button click or something
  this.refresh = function(id){
    Restangular.one('users', id).get().then(function(resp){
      this.user = resp;
    }.bind(this)); //The 'this' in the .bind() function is the 'this' of the data outside the function. Weird, I know.
  }
});

Unsure if this particularly resolves your problem, but it's one method I got very accustomed with when I was dealing with MooTools a lot.

Upvotes: 1

Michael Kang
Michael Kang

Reputation: 52867

this gets overridden depending on the execution context.

Instead, you should save this in a temp variable and reference it within your closure.

.controller('profileCtrl',      function(ProfileData, Restangular){
  // ProfileData comes from router.resolve

  var $this = this;
  $this.user = ProfileData;

  // I want to update the data with a button click or something
  $this.refresh = function(id){
    Restangular.one('users', id).get().then(function(resp){
      $this.user = resp;
    })
  }
});

That way, this is always what you expect it to be

Upvotes: 2

Related Questions