aghaux
aghaux

Reputation: 749

$scope.$watch not detecting changes in directive in same module

I'm implementing a watch in the controller, when user toggles a button. I have a watch inside the directive and that is working, e.g. it detects that the scope variable has changes but if I have a watch inside the controller it does not detects

    <button toggle-button active-text="Yes" inactive-text="No" ng-model="light.state">Show millions</button><br>

here is the code:

'use strict';
angular.module('fiveYearOverview', ['fiveYearOverviewServices', 'fiveYearOverviewDirectives'])
    .controller('fiveYearCtrl', [
        '$scope', 'reports',
        function ($scope, reports) {

            //not working
            $scope.$watch('lightState', function (newValue, oldValue) {
                if (newValue)
                    console.log("I see a data change!");
            }, true);

        }
    ])
    .directive('toggleButton', function () {
        return {
            require: 'ngModel',
            scope: {
                activeText: '@activeText',
                inactiveText: '@inactiveText',
                lightState: '=ngModel'
            },
            replace: true,
            transclude: true,

            template: '<div>' +
                '<span ng-transclude></span> ' +
                '<button class="btn" ng-class="{\'btn-primary\': state.value}" ng-click="state.toggle()">{{activeText}}</button>' +
                '<button class="btn" ng-class="{\'btn-primary\': !state.value}" ng-click="state.toggle()">{{inactiveText}}</button>' +
                '</div>',

            link: function postLink(scope) {

                scope.lightState = scope.inactiveText;
                scope.state = {
                    value: false,
                    toggle: function () {
                        this.value = !this.value;
                        scope.lightState = this.value ? scope.activeText : scope.inactiveText;
                        console.log(scope.lightState);

                        //working
                        scope.$watch('lightState', function (newValue, oldValue) {
                            if (newValue)
                                console.log("I see a data change!");
                        }, true);

                    }
                };
            }

        }
    });

What is that i'm doing wrong ?

Upvotes: 1

Views: 872

Answers (2)

Ankh
Ankh

Reputation: 5718

lightState is being declared in a scope below that of fiveYearCtrl making it inaccessible as outlined here.

An alternative solution could be to define the callback function in fiveYearCtrl and call it from the directive.

.controller('fiveYearCtrl', [
    '$scope', 'reports',
    function ($scope, reports) {
        this.consoleLog = function (newValue, oldValue) {
            if (angular.isDefined(newValue))
                console.log("I see a data change!");
        };
    }
])

link: function postLink(scope, element, attrs, ctrl) 
{
    scope.lightState = scope.inactiveText;
    scope.state = {
        value: false,
        toggle: function () {
            this.value = !this.value;
            scope.lightState = this.value ? scope.activeText : scope.inactiveText;
            console.log(scope.lightState);

            //working
            scope.$watch('lightState', ctrl.consoleLog, true);
        }
    };
}

Upvotes: 0

Nils Mehlhorn
Nils Mehlhorn

Reputation: 390

By defining a scope in the directive you are creating an isolated scope for it. Thats why you cant access its members from the controller.

Upvotes: 2

Related Questions