angularjsdata-bindingangularjs-directiveisolate-scope

Two way data binding with directive doesn't work


I have a controller used to add tasks. On that page a user needs to select a group to act upon. I have written a directive that is used to allow a user to pick groups (folders)

My page controller

function AddTaskController($scope) {
    var vm = this;

    vm.group = { whatsit: true };

    $scope.$watch("vm.group", function () {
        console.log("controller watch", vm.group);
    },true);
}

The page html where the directive is used

<em-group-selection group="vm.group"></em-group-selection>

The directive configuration

function GroupSelectionDirective() {
    return {
        scope: {
            group: '='
        },
        controller: GroupSelectionDirectiveController,
        controllerAs: 'vm',
        templateUrl: '/views/templates/common/folderselection.html'
    };
}

The directive controller:

function GroupSelectionDirectiveController($scope) {
    var vm = this;

    $scope.$watch("group", function () { console.log("yo1", vm.group); }, true)
    $scope.$watch("vm.group", function () { console.log("yo2", vm.group); }, true)
}

Now when this fires, both console.log() calls in the directive fire once, with undefined. They never fire again. If in the controller I set vm.group to something else the $watch in the AddTaskController never gets fired.

Why isnt the data binding working?


Update:

I notice that if, in the directive, I change the init() function in my directive to use $scope it works! Can I not, as Fedaykin suggests, use controllerAs with two way data binding?

function init() {
    $timeout(function () {
        $scope.group.shizzy = 'timeout hit';
    }, 200);
}

Solution

  • Turns out that if you use isolate scopes and controlelrAs syntax you need to also use bindToController : true. Without this you will not be able to only use vm and will have to use $scope for the isolate scope variables

    More information can be found in the John Papa style guide and this SO answer

    The final directive setup is as so:

    function GroupSelectionDirective() {
        return {
            scope: {
                group: '='
            },
            controller: GroupSelectionDirectiveController,
            controllerAs: 'vm',
            bindToController: true,
            templateUrl: '/views/templates/common/folderselection.html'
        };
    }