Angularjs "Controller As" Syntax - Clarification

AngularJs controller as syntax - clarification?

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.

  • $scope plunker
  • controller as plunker

JavaScript | Angular | Controller As Syntax: Cannot Use `this`

The problem is certainly not that this is a reserved word in JavaScript.
There is no rule in the controller as syntax that says you would need to assign the value of this to a variable with the same name as the controller and I'm pertty sure angular won't do such thing either. Why would it? That would be incredibly stupid use of Function constructor and just a needless bug.

There's a simple way to test that JavaScript reserved words are not the issue here. Name your controller "throw". "Parent as throw". throw is a reserved word, but does that throw errors? No. Does that work? Yes.

this is, however, reserved in the context of angular's own template expressions. It's used to refer to the current scope of the expression.

<div ng-controller="Parent as this">
{{log(this)}}
</div>

angular.module('testApp', []).controller('Parent', function($scope){
this.test = 'foo';
$scope.log = function(arg){
console.log(arg);
};
});

The above won't throw errors, but it won't log the controller either. Instead, it will log a scope object containing the log function and $parent and what not.

In fact, it will also contain something intresting to us: property this: Object, our controller.

And sure enough, change the template expression to {{log(this.this)}} and it will log the controller instance just fine. Still wouldn't use 'this' as the name though, it would probably just cause more bugs by mistake than undefined functions ever have.

Replace $scope with 'controller' as syntax

You basically found the reason why using this isn't a very good idea in controllers.
The this in your $http's success promise is not the this of the controller because this function gets executed in a different context. This wouldn't be an issue if you get $scope via the closure.

You can workaround that by defining a variable var that = this; and then use that instead.

Why should I use controllerAs syntax

You can see related Here

they both define variables in $scope

Angularjs Controller as or $scope

I've written a few answers to this question in the past, and they all essentially boil down to the same thing. In Angular, you are using $scope, even when you aren't expressly referencing it.

The ControllerAs syntax allows Angular to help you to write more efficient, fault tolerant controllers. Behind the scenes, when you use ng-controller="theController as ctrl", Angular creates theController as a property on $scope and assigns it as ctrl. You now have an object property you are referencing from scope, and are automatically protected from prototype inheritance issues.

From a performance perspective, since you are still using $scope, there should be little to no performance difference. However, since your controller is now not assigning variables directly to $scope on it's own, it does not need to have $scope injected. Also, the controller can much more easily be tested in isolation, since it is now just a plain JavaScript function.

From a forward thinking perspective, it's well known by now that Angular 2.0 will not have $scope, but instead will use features of ECMAScript 6. In any previews released by the Angular team showing migrations, they first begin by refactoring the controller to eliminate $scope. If your code is designed without the use of $scope based controllers, your first step in a migration is already complete.

From the designer's perspective, the ControllerAs syntax makes it much clearer where objects are being manipulated. Having customerCtrl.Address and storeCtrl.Address makes it much easier to identify that you have an address assigned by multiple different controllers for different purposes than if both used $scope.Address. Having two different HTML elements on a page which both are bound to {{Address}} and knowing which one is which only by the controller the element is contained in is a major pain to troubleshoot.

Ultimately, unless you are trying to spin up a 10 minute demo, you really should be using ControllerAs for any serious Angular work.

Angular Controller and controllerAs keyword usage in directive

Check out this plunkr code

Here is my simple Directive code:

angular.module('app', [])

.directive('someDirective', function () {
return {
scope: {},
controller: function ($scope) {
this.name = 'Pascal';
$scope.color = 'blue';
},
controllerAs: 'ctrl',
template: '<div>name: {{ctrl.name}} and Color: {{color}}</div>'
};
});

And The HTML

<body ng-app="app">
<some-directive />
</body>

So, as you can see, if you need to access some variable which were defined against this keyword in the controller, you have to use controllerAs. But if it was defined against $scope object you can just access it with its name.

For example, you can get the variable color just by using {{color}} as it was defined against $scope but you have to use {{ctrl.name}} as "name" was defined against this.

I don't think there really is much difference, as this answer says,

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

Also from their own website you can read the about the motivation behind this design choice,

Using controller as makes it obvious which controller you are
accessing in the template when multiple controllers apply to an
element

Hope it helps.

In Angular JS, $scope object approach of controller creation?

Finally I have the exact answer for which I am looking for

In AngularJS 1.2, the “controller as” syntax was introduced, and made controller code creation more readable.

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

myApp.controller("AddController", function ($scope) {
$scope.numb1;
$scope.numb2;
$scope.result;
$scope.add = function () {
$scope.result = $scope.numb1 + $scope.numb2;
}
});

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 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>

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

Having as ctrl in ng-controller versus not having it

John Papa's excellent Angular style guide (essential reading for all new Angular devs IMO) covers this rather well:

Why?: Controllers are constructed, "newed" up, and provide a single new instance, and the controllerAs syntax is closer to that of a JavaScript constructor than the classic $scope syntax.

Why?: It promotes the use of binding to a "dotted" object in the View (e.g. customer.name instead of name), which is more contextual, easier to read, and avoids any reference issues that may occur without "dotting".

Why?: Helps avoid using $parent calls in Views with nested controllers.

Points 2 and 3 are the key for me - it makes your code a lot easier to read and maintain.



Related Topics



Leave a reply



Submit