I can not understand the scope of the named controller in Angularjs and the use of the keyword this

advertisements

I'm trying to understand the use of named controllers (controller as syntax) in Angular.
In my app I have the same controller associated with some different divs. In html page the controllers is always named (myCtrl as C). And inside the controller I used this.
The controller has some variables and some methods bound/called within html page.

I have some strange behavior that I tried to replicate in this example:

var app=angular.module("myApp", []);

app.controller("ctrl", function(){
    vm=this
    vm.name="Pippo";
    vm.msg=function(){alert(vm.name)}
})

app.controller("ctrl2", function(){
    this.name="Pippo";
    this.msg=function(){alert(this.name)}
})

app.controller("ctrl3", function($scope){
    $scope.name="Pippo";
    $scope.msg=function(){alert($scope.name)}
});

http://jsfiddle.net/k66Za/111/

My case is the first one, the one using ctrl1. As you can see, what I expect clicking the first button is not what I get: instead of returning ctrl1 name it returns ctrl2 name.

Of course it's my lack, but I don't see the difference between ctrl1 and ctrl2. Could some one please explain to me what's happening in my example and if I should use $scope, this and, most of all, why using vm (where vm=this) is different from using this?


Technically there is no difference between ctrl and ctrl2. The reason why you should do what you did in ctrl and not what you did in ctrl2 is this:

It is a good idea to bind the controller this to a variable so that you can reference it later. this changes meaning depending on the context you use it in. If you reference this inside a function, it refers to that function. If you want to bind something to the controller from within a function, you cannot do it using this.

When we inject $scope into a controller, we use $scope as 'glue' between the controller and the view. A sort of mediator between the two. If we use controller as syntax we are dealing directly with the controller instance, and thus we must reference myCtrl.myVar instead of myVar (when it is attached to $scope).

You have this code in your fiddle:

<div ng-controller="ctrl2 as c"  ng-init="c.name=3">
        Name: <input type="text" ng-model="c.name" />
        <input type="button" ng-click="c.msg()" value="I should show {{c.name}}" ></input>
        </div>

        <div ng-controller="ctrl2 as c"  ng-init="c.name=4">
        Name: <input type="text" ng-model="c.name" />
        <input type="button" ng-click="c.msg()" value="I should show {{c.name}}" ></input>
        </div>

It may seem that this code is behaving strangely, but it actually isn't. Regardless of which button you click, they both give you back 4. This is because you are instantiating the same controller two times. When angular digests the page it hits the first instantiation, assigns 3 to c.name, then it hits the second instantiation, which assigns 4 to c.name, so when you try to call up a reference to c.name it is giving you the second value.