Exploring Angular’s “Controller as” Syntax and the vm Variable

Dhananjay Kumar / Thursday, July 02, 2015

Often, I hear developers ask “What is the ‘controller as’ syntax and how it is different from the $scope object approach of controller creation?” In this post we will learn about controller as syntax and compare it with the $scope object approach of controller creation. 

In AngularJS 1.2, the “controller as” syntax was introduced, and made controller code creation more readable. Let’s see both approaches in action below:

 

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>

 

Of course 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.

I hope you find this post useful - thanks for reading and Happy Coding!