13

I am working on an AngularJS tutorial, and I see the following code:

.state('index',{
  url:"/",
  templateUrl:"views/index.html",
  controller:"IndexCtrl",
  controllerAs:"index"
})

What is the reason someone would want to use the controllerAs property?

ruffin
  • 16,507
  • 9
  • 88
  • 138
Michael
  • 13,950
  • 57
  • 145
  • 288

4 Answers4

15

Few things:

1. Reduce scope usage

Instead of loading every data in the scope of a controller, you could simply use this to load up everything that you require.

eg:

Route

state('index',{
    url:"/",
    templateUrl:"views/index.html",
    controller:"ListCtrl",
    controllerAs:"list"
})

In Controller

angular.module('feed').controller('ListCtrl', function($scope, reddit){
    var vm   = this;
    vm.names = ["Michael", "Roy"];

});

In Template:

<ul>
    <li ng-repeat="name in list.names">
        <div>{{name}}</div>
    </li>
</ul>

2. Correct scope usage

When multiple controllers come into play, scope becomes a tricky thing. Using controllerAs method will go a long way is resolving this. An example is shown below:

Wrong:

<span>Outside Controller: Your name is: {{username}}</span>
<div ng-controller="SignupController">
    <span>Inside Controller: Your name is: {{username}}</span>
    <fieldset legend="User details">
        <input ng-model="username">
    </fieldset>
</div>

Correct:

<span>Outside Controller: Your name is: {{user.name}}</span>
<div ng-controller="SignupController">
    <span>Inside Controller: Your name is: {{user.name}}</span>
    <fieldset legend="User details">
        <input ng-model="user.name">
    </fieldset>
</div>

Found an image which makes everthing more clear:

enter image description here

Courtesy : AngularJs "controller as" syntax - clarification?

Community
  • 1
  • 1
Roy M J
  • 6,926
  • 7
  • 51
  • 78
  • 3
    `There are performance improvements as well if we minimize the use of $scope`, How though? Can you explain that?. I thought controllerAlias is just added as a property on the scope (scope created for the controller) with its value as that of the controller instance. So you are not minimizing the use of $scope, of course directly. I agree with the other parts in the answer. – PSL Aug 05 '15 at 17:37
  • In point 1, how does ` controller:"ListCtrl",` link to `vm`? And should not `
    {{name}}
    ` be `
    {{vm.name}}
    `?
    – Mawg says reinstate Monica Feb 17 '20 at 12:48
4

Yes. A little more info:

Before the controllerAs syntax, methods and properties needed to be exposed to views by binding them to the $scope. With controllerAs, your controller instance is bound to the $scope as the property you select.

This way you can use Plain Old JavaScript Classes for your controllers.

Editorial: This is a much cleaner approach to development. One of the things that makes Angular so easy to write tests for is that your Controllers and components do not need to inherit from framework base-classes. See Backbone and Ember.

So with the old style your controllers would look like (in ES6 for simplicity):

YourController.$inject = ['$scope'];
class YourController {
  
    constructor($scope) {

        $scope.myMethod = () => { . . . };

        $scope.myProperty = true;
    }
}

With the controllerAs

class YourController {
  
    constructor() {

        this.myProperty = true;
    }

    myMethod() { . . . };
}

Just a plain old class rather than decorating or monkeypatching the $scope.

ruffin
  • 16,507
  • 9
  • 88
  • 138
Martin
  • 15,820
  • 4
  • 47
  • 56
  • I was with you up until, "_This is a much cleaner approach to development_". Now we've got a discoverable, but not _extremely_ so (thus OP's question), reference exposure that additionally forces you to use `this`, which, [as Crockford describes](https://jslint.com/help.html#this) isn't objectively great: "_Having `this` in the language makes it harder to talk about the language. It is like pair programming with Abbott and Costello._" But if we leave the subjective angle out, this answer does a great job accurately reflecting why someone _would_ stoop so low. ;^D – ruffin Jul 16 '20 at 14:20
  • this and new are part of the language. There are tools like TypeScript and/or ESLint that solve the problems that Crockford describes without the need to ignore major features of JavaScript. – Martin Jul 16 '20 at 18:51
  • Just pointing out that you've explained why `controllerAs` is used, but that people smarter than, well, _me_ at least might disagree that its use is indisputably an improvement. `controllerAs` is a convention, and it's one level more esoteric than `$scope`, which already gave you a ready-made outlet for exposing references (though [Roy's answer covers some edgy conditions where `$scope` strains](https://stackoverflow.com/a/31838488/1028230)). In any event, one could, and often does, do worse than to follow Crockford's advice. – ruffin Jul 16 '20 at 20:44
1

maybe you didn't googled enough!

http://toddmotto.com/digging-into-angulars-controller-as-syntax/

As the name "controllerAs" tell us, is an alias for controller them you can access your controller with that alias.

cagica
  • 678
  • 4
  • 23
1

You can set your controller in many ways like :

$stateProvider.state('contacts', {
  template: '<h1>{{title}}</h1>',
  controller: function($scope){
    $scope.title = 'My Contacts';
  }
})

Or if you already have a controller defined on the module, like this:

$stateProvider.state('contacts', {
  template: ...,
  controller: 'ContactsCtrl'
})

Alternatively using the controllerAs syntax the above become:

$stateProvider.state('contacts', {
  template: '<h1>{{contact.title}}</h1>',
  controller: function(){
    this.title = 'My Contacts';
  },
  controllerAs: 'contact'
})

and

$stateProvider.state('contacts', {
  template: ...,
  controller: 'ContactsCtrl as contact'
})

Or for more advanced needs you can use the controllerProvider to dynamically return a controller function or string for you:

$stateProvider.state('contacts', {
  template: ...,
  controllerProvider: function($stateParams) {
      var ctrlName = $stateParams.type + "Controller";
      return ctrlName;
  }
})

Source : https://github.com/angular-ui/ui-router/wiki#controllers

Simply, Controller as syntax helps when we are working with nested controllers. The named scopes are clearly defined so there won’t be conflicts between controllers since you must state which controller you’re referencing before the dot.

<div ng-controller="Shell as shellVm">
  <h1>{{shellVm.title}}</h1>
  <article ng-controller="Customers as customersVm">
    <h2>{{customersVm.title}} in {{shellVm.title}}</h2>
    <ul ng-repeat="c in customersVm.customers">
      <li>{{c.name}}</li>
    </ul>
  </article>
</div>

Refer AngularJs "controller as" syntax - clarification? as well.

Community
  • 1
  • 1
Darshan Patel
  • 2,839
  • 2
  • 25
  • 38