2

I have lately switched to using "this" in the controllers and controllerAs in ngRoute and Directives, rather than $scope directly. Although I really enjoy the way the code looks, I have to bind "this" to each function - manually.

Example:

app.controller('mainController', function ($scope, Restangular) {
    this.title = '';

    $scope.$on('changeTitle', function (event, data) {
        this.title = data;
    }.bind(this)); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

});

I understand why I have to do that ("this" context constantly changes), is there any better solution (cleaner, usable) I should consider doing?

Thanks.

user3043893
  • 311
  • 4
  • 12

3 Answers3

8

Fat arrow functions in ES6 are specifically added to solve this problem. With a fat arrow function you inherit the context of the parent scope, so you no longer have to use bind or var that = this. So you could look into transpiring.

app.controller('mainController', function ($scope, Restangular) {
  this.title = '';

  $scope.$on('changeTitle', (event, data) => {
    this.title = data;
  });
});

Angular 2 is written in ES6 and uses the Traceur compiler: http://angularjs.blogspot.sg/2014/03/angular-20.html and here's a short post on how you can use it with your own code: http://www.benlesh.com/2014/03/traceur-is-awesome-but-still-little.html

Kit Sunde
  • 35,972
  • 25
  • 125
  • 179
  • I am getting "Uncaught SyntaxError: Unexpected token =>". It seems like a good solution (I'm using Angular 1.4) – user3043893 Jul 24 '15 at 22:58
  • @user3043893 Only the latest Firefox has native support for arrow functions so far, so you need to convert from ES6 to ES5 to run it in most browsers, which the second link tells you how. There are also ways to automate that with grunt/gulp/broccoli or whatever angular people normally use to make it easier on yourself. If it seems overly complicated I would just stick with what you're already doing until you feel more familiar. – Kit Sunde Jul 24 '15 at 23:02
3

The simplest way is to put your this inside an object.

app.controller('mainController', function ($scope, Restangular) {
  var self = this;
  self.title = ''; 

  $scope.$on('changeTitle', function (event, data) {
    self.title = data;     // Due to scope inheritance in javascript, self is defined here.   
  });

});

This version is also best practice for many of angular users, including John Papa (he calls it vm instead of self).

https://github.com/johnpapa/angular-styleguide#style-y032

Deblaton Jean-Philippe
  • 11,188
  • 3
  • 49
  • 66
0

And you can use the

Angular.bind(this, function(){})

as described here and in this answer

so you will have something like:

this.defaultCity = 'myvalue';
callHttpService(this.defaultCity).then(angular.bind(this, function(res) {
    this.defaultCity = res.data;
}));
Gader
  • 43
  • 7