0

I'm having troubles updating a variable on my controller's $scope from within a directive binding to those variables. For instance, I'm trying update the value with a setter-function whenever I move my mouse, but the value never gets updated.

I have made a fiddle here: http://jsfiddle.net/23hdsueb/

Any ideas how to set variables on the parent scope from my directive?


HTML:

<body ng-app="testApp" ng-controller="TestController">
    <p>
        outside directive
    </p>
    <input type="text" name="name" ng-model="obj.value">
    <p>
        value: {{obj.value}}
    </p>
    <test value="obj.value" set-value="setValue"></test>
</body>

JS:

angular.module('testApp', [])

.controller('TestController', ['$scope', function ($scope) {
    $scope.obj = {
        value: 'initial value'
    };
    $scope.setValue = function (val) {
        $scope.obj.value = val;
    };
}])

.directive('test', ['$document', function ($document) {
    return {
        restrict: 'E',
        scope: {
            value: '=',
            setValue: '='
        },
        template: '<div class="test">inside directive<br>value: {{value}}</div>',
        link: function (scope, element, attrs) {
            $document.on('mousemove', function (event) {
                scope.setValue(event.pageX + ' : ' + event.pageY);
            });
        }
    };
}]);
  • You are calling the `function` on attribute of directive wrong: In your DDO should be `scope: {setValue: "&"}` Please refer: http://stackoverflow.com/questions/33454526/how-to-update-controllers-scope-variable-from-child-directive/#33454756 – Kulbhushan Singh Oct 31 '15 at 18:03

2 Answers2

1

Sorry for not giving the right answer in the first try, I had not understood the question properly. The answer is that your whole code is right except that you're missing one line of code. Normally you don't need to add it, but you do need to add it here.

$document.on('mousemove', function (event) {
  scope.setValue(event.pageX + ' : ' + event.pageY);
  scope.$apply();
});

While $document is an angularized variable, $document.on is not really the angular way of attaching event handlers to events.

Why is it good to follow angularized ways? Because they automatically run scope.$apply() when the command completes. The apply() function triggers a digest cycle which is responsible for angular's powers. The digest cycle among many things, checks if there are binded variables which need to be updated or not.

If you use ng-mousemove then you won't need the scope.$apply() line because the ng-mousemove directive triggers the digest cycle when it is fired.

ArslanW
  • 353
  • 1
  • 10
  • Thanks for the explanation! When I get rep. I will upvote this answer. –  Oct 31 '15 at 18:38
0

What you are missing is, syntax for calling function of controller via directive /or/ How to call method in attribute of directive: TL:DR you may go through beautiful explanation about same by Dan Wahlin

In your directive:

.directive('test', ['$document', function ($document) {
    return {
        restrict: 'E',
        scope: {
            value: '=',
            setValue: '&'//for function it should be &
        },
        template: '<div class="test">inside directive<br>value: {{value}}</div>',
        link: function (scope, element, attrs) {
            $document.on('mousemove', function (event) {
                //argVal should be exact name in the function call mentioned in directive's attribute
                scope.setValue({argVal: event.pageX + ' : ' + event.pageY});
            });
        }
    };
}]);

And your directive use should be like: Please Note: argVal should match exactly as in call to function from within link function call

<test value="obj.value" set-value="setValue(argVal)"></test>

For detail please refer: SO question

Community
  • 1
  • 1
Kulbhushan Singh
  • 536
  • 5
  • 18