AngularJs "controller as" syntax - clarification?

JavascriptAngularjs

Javascript Problem Overview


I read about the new syntax from angularJS regarding controller as xxx

> The syntax InvoiceController as invoice tells Angular to instantiate > the controller and save it in the variable invoice in the current > scope.

Visualization :

enter image description here

Ok , so I wont have the parameter $scope in my controller and the code will be much cleaner in the controller.

But

I will have to specify another alias in the view

So Until now I could do :

<input type="number" ng-model="qty"  />

....controller('InvoiceController', function($scope) {
   // do something with $scope.qty <--notice

And now I can do :

 <input type="number" ng-model="invoic.qty"  /> <-- notice 

  ....controller('InvoiceController', function() {
       // do something with  this.qty  <--notice

Question

What is the goal of doing it ? removing from one place and add to another place ?

I will be glad to see what am I missing.

Javascript Solutions


Solution 1 - Javascript

There are several things about it.

Some people don't like the $scope syntax (don't ask me why). They say that they could just use this. That was one of the goals.

Making it clear where a property comes from is really useful too.

You can nest controllers and when reading the html it is pretty clear where every property comes.

You can also avoid some of the dot rule problems.

For example, having two controllers, both with the same name 'name', You can do this:

<body ng-controller="ParentCtrl">
    <input ng-model="name" /> {{name}}
    
    <div ng-controller="ChildCtrl">
        <input ng-model="name" /> {{name}} - {{$parent.name}}
    </div>
</body>

You can modify both parent and child, no problem about that. But you need to use $parent to see the parent's name, because you shadowed it in your child controller. In massive html code $parent could be problematic, you don't know where that name comes from.

With controller as you can do:

<body ng-controller="ParentCtrl as parent">
    <input ng-model="parent.name" /> {{parent.name}}
    
    <div ng-controller="ChildCtrl as child">
      <input ng-model="child.name" /> {{child.name}} - {{parent.name}}
    </div>
</body>

Same example, but it is much much clearer to read.

Solution 2 - Javascript

The main advantage with controller as syntax I see is that you can work with controllers as classes, not just some $scope-decorating functions, and take advantage of inheritence. I often run into a situation when there's a functionality which is very similar to a number of controllers, and the most obvious thing to do is to create a BaseController class and inherit from it.

Even though there's is $scope inheritence, which partially solves this problem, some folks prefer to write code in a more OOP manner, which in my opinion, makes the code easier to reason about and test.

Here's a fiddle to demonstrate: http://jsfiddle.net/HB7LU/5796/

Solution 3 - Javascript

I believe one particular advantage is clear when you have nested scopes. It will now be completely clear exactly what scope a property reference comes from.

Solution 4 - Javascript

Source

Difference between Creating a controller using the $scope object and Using the “controller as” syntax and vm

Creating a controller using the $scope object

Usually we create a controller using the $scope object as shown in the listing below:

myApp.controller("AddController", function ($scope) {

 

    $scope.number1;

    $scope.number2;

    $scope.result;

    $scope.add = function () {

        $scope.result = $scope.number1 + $scope.number2;

    }

});

Above we are creating the AddController with three variables and one behaviour, using the $scope object controller and view, which talk to each other. The $scope object is used to pass data and behaviour to the view. It glues the view and controller together.

Essentially the $scope object performs the following tasks:

  1.   Pass data from the controller to the view
    
  2.   Pass behaviour from the controller to the view
    
  3.   Glues the controller and view together
    
  4.   The $scope object gets modified when a view changes and a view gets modified when the properties of the $scope object change
    

We attach properties to a $scope object to pass data and behaviour to the view. Before using the $scope object in the controller, we need to pass it in the controller function as dependencies.

Using the “controller as” syntax and vm

We can rewrite the above controller using the controller as syntax and the vm variable as shown in the listing below:

myApp.controller("AddVMController", function () {

    var vm = this;

    vm.number1 = undefined;

    vm.number2=undefined;

    vm.result =undefined;

    vm.add = function () {

        vm.result = vm.number1 + vm.number2;

    }

});

Essentially we are assigning this to a variable vm and then attaching a property and behaviour to that. On the view we can access the AddVmController using controller as syntax. This is shown in the listing below:

<div ng-controller="AddVMController as vm">

            <input ng-model="vm.number1" type="number" />

            <input ng-model="vm.number2" type="number" />

            <button class="btn btn-default" ng-click="vm.add()">Add</button>

            <h3>{{vm.result}}</h3>

  </div>

Ofcourse we can use another name than “vm” in the controller as syntax. Under the hood, AngularJS creates the $scope object and attaches the properties and behaviour. However by using the controller as syntax, the code is very clean at the controller and only the alias name is visible on the view.

Here are some steps to use the controller as syntax:

  1.   Create a controller without $scope object.
    
  2.   Assign this to a local variable. I preferred variable name as vm, you can choose any name of your choice.
    
  3.   Attach data and behaviour to the vm variable.
    
  4.   On the view, give an alias to the controller using the controller as syntax.
    
  5.   You can give any name to the alias. I prefer to use vm unless I’m not working with nested controllers.
    

In creating the controller, there are no direct advantages or disadvantages of using the $scope object approach or the controller as syntax. It is purely a matter of choice, however, using the controller as syntax makes the controller’s JavaScript code more readable and prevents any issues related to this context.

Nested controllers in $scope object approach

We have two controllers as shown in the listing below:

myApp.controller("ParentController", function ($scope) {

 

    $scope.name = "DJ";

    $scope.age = 32;

});

myApp.controller("ChildController", function ($scope) {

 

    $scope.age = 22;

    $scope.country = "India";

 

});

The property “age” is inside both controllers, and on the view these two controllers can be nested as shown in the listing below:

<div ng-controller="ParentController">

 

            <h2>Name :{{name}} </h2>

            <h3>Age:{{age}}</h3>

 

             <div ng-controller="ChildController">

                    <h2>Parent Name :{{name}} </h2>

                    <h3>Parent Age:{{$parent.age}}</h3>

                    <h3>Child Age:{{age}}</h3>

                    <h3>Country:{{country}}</h3>

             </div>

        </div>

As you see, to access the age property of the parent controller we are using the $parent.age. Context separation is not very clear here. But using the controller as syntax, we can work with nested controllers in a more elegant way. Let’s say we have controllers as shown in the listing below:

myApp.controller("ParentVMController", function () {

    var vm = this;

    vm.name = "DJ";

    vm.age = 32;

});

myApp.controller("ChildVMController", function () {

    var vm = this;

    vm.age = 22;

    vm.country = "India";

 

});

On the view these two controllers can be nested as shown in the listing below:

<div ng-controller="ParentVMController as parent">

 

            <h2>Name :{{parent.name}} </h2>

            <h3>Age:{{parent.age}}</h3>

 

            <div ng-controller="ChildVMController as child">

                <h2>Parent Name :{{parent.name}} </h2>

                <h3>Parent Age:{{parent.age}}</h3>

                <h3>Child Age:{{child.age}}</h3>

                <h3>Country:{{child.country}}</h3>

            </div>

 </div>

In the controller as syntax, we have more readable code and the parent property can be accessed using the alias name of the parent controller instead of using the $parent syntax.

I will conclude this post by saying that it’s purely your choice whether you want to use the controller as syntax or the $scope object. There is no huge advantage or disadvantage to either, simply that the controller as syntax you have control on the context is a bit easier to work with, given the clear separation in the nested controllers on the view.

Solution 5 - Javascript

I find the main advantage is a more intuitive api since the methods/properties are associated with the controller instance directly and not the scope object. Basically, with the old approach, the controller becomes just a decorate for building up the scope object.

Here are some more info on this: http://www.syntaxsuccess.com/viewarticle/551798f20c5f3f3c0ffcc9ff

Solution 6 - Javascript

From what I've read, $scope will be removed in Angular 2.0, or at least how we view the use of $scope. It might be good to start using controller as as the release of 2.0 nears.

Video link here for more discussion on it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRoyi NamirView Question on Stackoverflow
Solution 1 - JavascriptJesus RodriguezView Answer on Stackoverflow
Solution 2 - JavascriptRoman KolpakView Answer on Stackoverflow
Solution 3 - JavascriptDavid M. KarrView Answer on Stackoverflow
Solution 4 - JavascriptShibinRaghView Answer on Stackoverflow
Solution 5 - JavascriptTGHView Answer on Stackoverflow
Solution 6 - Javascriptthank_youView Answer on Stackoverflow