Ciel
Ciel

Reputation: 4440

angularjs - difficulty replacing "$scope" with "this" and similar

I am attempting to slightly reduce the clutter of $scope in my angular application, pursuant to several tutorials on the subject. One such article demonstrates a good tactic for cleaning up $scope is to instead make my controllers 'classes', so to speak. Like this;

//Don't do this
app.controller('MyCtrl', function($scope){
  $scope.doStuff = function(){
    //Really long function body
  };
});

//Do this instead
var MyCtrl = function($scope){
  var _this = this;

  _this.doStuff = function(){
    _this.doStuff();
  };
};

I am attempting to do this, but am having a great deal of trouble - as it seems that code attached to _this is completely different than code attached to $scope. For instance;

var editor = function($scope){
   var _this = this;

   _this.Model = {
      Id: null,
      Editing: false
   };

   _this.options = {
      columns : [
         { field: "Id", width: 25, title: "Identity" },
         { field: "Name", width: 40, title: "Name" }
      ]
   };
};

And then attempting to use this in directives ...

var gridDirective = function($parse) {
   return {
      restrict: 'A',
      scope: true,
      link: function(scope, element, attributes, controller) {
         // I expected this line to output the array I made, but it comes up undefined
         console.log('scope.options: ', scope.options);
      }
   }
};

I expected the objects I assigned to _this to be available on the scope in the directive, but this doesn't happen. It is only when I directly, explicitly assign them to $scope do I see them show up in a directive.

Is there any solution to this? Or do I just have to use $scope everywhere?

Upvotes: 0

Views: 1717

Answers (3)

Narek Mamikonyan
Narek Mamikonyan

Reputation: 4611

In your case, if you want achieve using this instead of $scope, you should do it like this:

var editor = function($scope){
   var _this = $scope;

   _this.Model = {
      Id: null,
      Editing: false
   };

   _this.options = {
      columns : [
         { field: "Id", width: 25, title: "Identity" },
         { field: "Name", width: 40, title: "Name" }
      ]
   };
};

But this approach doesn't make sense. The article suggestion is (and in my opinion also)

for controllers use constructor pattern what does it mean? and what the advantages of that, you will have private which you can not assign to scope and you will have functions which will be assigned to scope by your choose, this will be keep your controller cleaner. Example from this article I think is not right, it should be like this:

var MyCtrl = function($scope){
  var _this = this;

  $scope.doStuff = _this.doStuff;
};

MyCtrl.prototype.doStuff = function(){
  //Really long function body, also this bounded with scope
};

MyCtrl.prototype.anotherFunc= function(){
  //This is another function which not bounded to scope
};

UPDATE

I would like to suggest read this article in this article explained styleguide for angular.

Upvotes: 1

ryeballar
ryeballar

Reputation: 30098

You can access these properties in the alias that you have provided in the ng-controller as notation within the scope of the controller's context. So if you're declaring the controller like this:

ng-controller="EditorController as editor"

this means that you can access the editor properties within the $scope.editor property.

DEMO

Javscript

.controller('EditorController', function() {

    var _this = this;

   _this.Model = {
      Id: null,
      Editing: false
   };

   _this.options = {
      columns : [
         { field: "Id", width: 25, title: "Identity" },
         { field: "Name", width: 40, title: "Name" }
      ]
   };

})

.directive('grid', function($parse) {
    return {
        restrict: 'A',
        scope: true,
        link: function(scope, element, attributes) {
            // I expected this line to output the array 
            // I made, but it comes up undefined
            console.log(scope.editor.options);
        }
    }
});

HTML

<div ng-app="demo" ng-controller="EditorController as editor">
    <div grid></div>
</div>

UPDATE

Since your directive is already defined with an isolated scope, you better make use of defining the properties and accessing the objects assigned from it, rather than accessing them from the parent scope.

JAVASCRIPT

.directive('grid', function($parse) {
    return {
        restrict: 'A',
        scope: {
          options: '='
        },
        link: function(scope, element, attributes) {
            console.log(scope.options);
        }
    }
});

HTML

<div ng-app="demo" ng-controller="EditorController as editor">
    <div grid="editor.options"></div>
</div>

You can learn more about isolate scopes and directives in the $compile service.

Upvotes: 1

Dalorzo
Dalorzo

Reputation: 20014

$scope needs to be set to _this instead of just this or this to local var at controller level.

A quick sample demo:

app.controller('MainController', function(){
  var vm = this;
  vm. error = '';
  vm.onUserComplete = function(response){
    console.log(vm.error);
  };

});

John Papa had recommended an approach where you could create Controllers methods using this. However, I personally I do see the benefit of deviating from the standard but if you want to read more about this approach here is the article that explains it:

http://www.johnpapa.net/angularjss-controller-as-and-the-vm-variable/

Upvotes: 1

Related Questions