angular-styleguide icon indicating copy to clipboard operation
angular-styleguide copied to clipboard

Directive controllerAs and scope

Open facultymatt opened this issue 10 years ago • 7 comments

When using multiple directives that use the controllerAs: 'vm' syntax and do not have scope, they will conflict and vm will get overwritten. For example, the following directives will not work as expected:

angular
    .module('app')
    .directive('myExampleOne', myExampleOne);

function myExampleOne() {
    var directive = {
        templateUrl: 'app/feature/example.directiveOne.html',
        controllerAs: 'vm',
        bindToController: true 
    };
    return directive;
}

angular
    .module('app')
    .directive('myExampleTwo', myExampleTwo);

function myExampleTwo() {
    var directive = {
        templateUrl: 'app/feature/example.directiveTwo.html',
        controllerAs: 'vm',
        bindToController: true 
    };
    return directive;
}

A few questions here:

  1. Does it make sense to always use scope? scope: {} or even scope: true will fix this issue. In my experience this is good practice to avoid scope conflicts even sans controllerAs.
  2. Should we not use bindToController in these examples?

Related style

https://github.com/johnpapa/angular-styleguide#style-y075

facultymatt avatar Sep 25 '15 18:09 facultymatt

I'd say that it is a good practice to always create a new scope for directives.

lunks avatar Sep 28 '15 17:09 lunks

using only isolated scopes, gives you more control over the dataflow of your application. and yes since angular 1.4 you should always use bindToController with isolated scopes and controllerAs.

jansepke avatar Sep 28 '15 18:09 jansepke

Any changes on angular 1.4 that makes this different than 1.3, @Jandalf?

lunks avatar Sep 29 '15 03:09 lunks

@lunks yes bindToController supports now an object value to follow the angular 2 binding style

e.g.: scope: {}, bindToController {param1: '='}

see #543

jansepke avatar Sep 29 '15 07:09 jansepke

Are isolated scopes not bad for composability (more directives on one element)? Since Angular 1.2 there is an error Multiple Directive Resource Contention when using multiple directives with isolated scopes. For instance:

<input my-directive my-second-directive ng-model="title">
angular.module('app', []).directive('myDirective', function () {
  return {
    restrict: 'A',
    scope: {}
  };
}).directive('mySecondDirective', function () {
  return {
    restrict: 'A',
    scope: {}
  };
});

Demo on Plunker

Resulting error: https://docs.angularjs.org/error/$compile/multidir?p0=myDirective&p1=mySecondDirective&p2=new%2Fisolatedundefinedcope&p3=undefined

karlhorky avatar Dec 02 '15 09:12 karlhorky

I've opened #608 for an answer to this.

karlhorky avatar Dec 02 '15 15:12 karlhorky

For this reason I would like an alternative answer to this question though - without using isolated scope. One thing I can imagine is to rename controllerAs based on the directive name.

angular
    .module('app')
    .directive('myExampleOne', myExampleOne);

function myExampleOne() {
    var directive = {
        templateUrl: 'app/feature/example.directiveOne.html',
        controllerAs: 'myExampleOneVm',
        bindToController: true 
    };
    return directive;
}

angular
    .module('app')
    .directive('myExampleTwo', myExampleTwo);

function myExampleTwo() {
    var directive = {
        templateUrl: 'app/feature/example.directiveTwo.html',
        controllerAs: 'myExampleTwoVm',
        bindToController: true 
    };
    return directive;
}

This would still not solve nested directives of the same type though...

karlhorky avatar Dec 02 '15 16:12 karlhorky