1

Directive scope values(initialValue and title) are undefined in my controller function - counterController. It prints initialValue if I define it like {{ counterCtrl.initialValue }} in app_counter.directive.html, but undefined in counterController function.

app_counter.directive.js

'use strict';

module.exports = function (app) {
    app.directive('appCounter', appCounter)
};

function appCounter() {
    let directive = {
        restrict: 'EA',
        template: require('./app_counter.directive.html'),
        scope: {
            initialValue: '=',
            title: '@'
        },

        controller: counterController,
        controllerAs: 'counterCtrl',
        bindToController: true
    };

    return directive;
}

function counterController() {
    let vm = this;

    vm.counter = vm.initialValue;
    vm.increment = increment;
    vm.decrement = decrement;

    function increment() {
        vm.counter += 1;
    }

    function decrement() {
        vm.counter -= 1;
    }
}

app.js

'use strict';

const angular = require('angular');
const app = angular.module('app', []);

require('./app_counter/app_counter.directive')(app);

app_counter.directive.html

<div class="counter">
    <div>Current value {{counterCtrl.title}}: {{ counterCtrl.counter }}</div>
    <button type="button" ng-click="counterCtrl.decrement()">Decrement</button>
    <button type="button" ng-click="counterCtrl.increment()">Increment</button>
</div>

index.html

<div id="app" ng-app="app">
    <app-counter title="hello" initial-value="10"></app-counter> 
</div>
0

1 Answer 1

2

You need to access them with $scope (as they are) inside your controller instead using your controller instance object (this) directly.

function counterController($scope) {
    let vm = this;

    vm.counter = $scope.initialValue;
    vm.increment = increment;
    vm.decrement = decrement;

    function increment() {
        vm.counter += 1;
    }

    function decrement() {
        vm.counter -= 1;
    }
}

>> Demo fiddle


By using bindToController:

You can achieve the same by using bindToController which is available since AngularJS v1.3:

myApp.directive('myDirective', function () {
    return {
      restrict: 'A',
      scope: true,
      controllerAs: 'counterCtrl',
      bindToController: {
        initialValue: '='
      },
      controller: function () { 
        this.$onInit = function () {

            let vm = this;

            vm.counter = vm.initialValue;
            vm.increment = increment;
            vm.decrement = decrement;

            function increment() {
                vm.counter += 1;
            }

            function decrement() {
                vm.counter -= 1;
            }
        };
      }
    }
});

>> Demo fiddle

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

8 Comments

But I want pass parameters inside the directive and catch them in controller. Is it possible?
@YevhenRadionov no, but you can use E2E binding or parse/access them as scope param or service/factory.
Actually, using the bindToController option on a directive should bind them to the controller instead of the scope. If you add bindToController: true to the directive configuration in the fiddle, you'll see that the $scope passed into the controller no longer has a title attribute and it is instead on the this of the controller. @YevhenRadionov, is that what you want?
@lin so parameters that I pass as a directive attributes I can use only in directive template, right?
@james00794 yes, he is able to achieve this in different ways. I added an example of how to do it with bindToController. Cheers m8
|

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.