4

I've a controller with some items for ng-repeat and each item should get a random color so I use ng-style with a function in that controller called randColor(...).

app.controller('TestController', function() {
    var vm = this;

    vm.items = [ { name: 'item 1' } , { name: 'item 2'} ];

    vm.randColor = function (item) {
        if (!item) {
            return 'red';
        }
        else if (!item.color)
        {
            var color = 'rgb('
                + _.random(0, 255) + ','
                + _.random(0, 255) + ','
                + _.random(0, 255) + ')';
            item.color = color;
        }

        return item.color;
    };
});

I'm using the "controller as" syntax for this and I usually always use vm as the short name of my controllers. I've never had a problem with doing so, even when naming "sub"-controllers the same way.

But now I've tried to do the same thing with a directive and suddenly my randColor(...) function stopped working.

Here is a plunker of my problem.

HTML:

<body ng-controller="TestController as vm">
    <!-- This works -->
    <h3>Without Directive (controllerAs: 'vm')</h3>
    <div ng-repeat="item in vm.items">
        <div ng-style="{ background: vm.randColor(item) }" class="container">
            <h4>{{ item.name }}</h4>
            <div ng-controller="TestDirectiveController as vm">
                <div>{{ vm.title }}</div>
            </div>
        </div>
    </div>

    <!-- This works -->
    <h3>Test Directive Alternative (controllerAs: 'directiveVM')</h3>
    <div ng-repeat="item in vm.items">
        <div ng-style="{ background: vm.randColor(item) }" class="container">
            <h4>{{ item.name }}</h4>
            <test-directive-alt></test-directive-alt>
        </div>
    </div>

    <!-- This DOES NOT work -->
    <h3>Test Directive (controllerAs: 'vm')</h3>
    <div ng-repeat="item in vm.items">
        <div ng-style="{ background: vm.randColor(item) }" class="container">
            <h4>{{ item.name }}</h4>
            <test-directive></test-directive>
        </div>
    </div>
</body>

JS:

app.controller('TestDirectiveController', function() {
    var vm = this;

    vm.title = 'test';
});

app.directive('testDirective', function() {
        return {
            restrict: 'EA',
            controller: 'TestDirectiveController',
            controllerAs: 'vm',
            bindToController: true,
            template: '<div>{{ vm.title }}</div>'
        };
    });

app.directive('testDirectiveAlt', function() {
        return {
            restrict: 'EA',
            controller: 'TestDirectiveController',
            controllerAs: 'directiveVM',
            bindToController: true,
            template: '<div>{{ directiveVM.title }}</div>'
        };
    });

Output:

enter image description here

I know I could just use a different name for the controller as in my example, but why does this happen in the first place?

And is there a way to get it working with the same name?

2
  • 2
    Did you try to define a new scope? The problem might be that the directive is using the the same scope as the one where vm is defined. For that reason it might not work. You can add a scope to the directive. Commented Jun 12, 2015 at 13:34
  • 2
    Yikes, you are totally right, by just adding scope: true it worked...there goes the last 3 hours of my life. You can formulate it to an answer if you want to get the credit for it! Thanks anyways :) Commented Jun 12, 2015 at 13:39

1 Answer 1

8

The problem you're facing seems to be related to the fact that the directive is being executed on the same scope as the scope where the controller is defined as vm.

What you need to do is to create a new scope scope: {} within the directive.

app.directive('testDirective', function() {
        return {
            restrict: 'EA',
            scope: {},
            controller: 'TestDirectiveController',
            controllerAs: 'vm',
            bindToController: true,
            template: '<div>{{ vm.title }}</div>'
        };
    });

With that, the controllerAs should create a new vm attribute in the directive scope.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.