Reputation: 1921
I've got a directive that shares data with its controller, which I'm doing with an isolate scope.
However, when I update the data from inside the directive, neither the directive nor the controller sees the data change using $watch.
Here's an example of what I'm trying to do:
var app = angular.module('myApp', []);
app.controller('myAppCtrl', function($scope) {
$scope.buttonSettings = {
val: 0
}
$scope.$watch('buttonSettings.val', function(val) {
console.log('watchInController')
console.log(val)
});
});
app.directive('buttonTest', function() {
return {
restrict: 'E',
scope: {
buttonSettings: '='
},
template: '<button>{{buttonSettings.val}}</button>',
link: function(scope) {
var button = $('button');
console.log(scope.buttonSettings)
scope.$watch('buttonSettings.val', function(val) {
console.log('watchInDirective')
console.log(val)
});
button.bind('mouseover', function() {
scope.buttonSettings.val++;
console.log('mouseover')
console.log(scope.buttonSettings.val)
})
}
}
});
And here's the full example in plunkr: http://plnkr.co/edit/lnztoMhtU03Qzl0BaMpk?p=preview
What am I doing wrong?
Upvotes: 1
Views: 719
Reputation: 43745
halilb is correct that you should not be using jQuery to select element, but instead use the element that Angular provides to your directive, and that $scope.$apply
is needed in order to register events that occur outside of Angular's context. However, you don't at all need to make a new directive to solve your problem here. Just use Angular's ngMouseover
directive. You can bind a function to it or just add your logic directly in. Here's a very minimal, simple example.
<div ng-init="foo = 1">Value: {{foo}}</div>
<button ng-mouseover="foo = foo+1">Mouse over this: {{foo}}</button>
Here's how the same code looks with the logic moved to the controller:
<div>Value: {{foo}}</div>
<button ng-mouseover="incrementFoo()">Mouse over this: {{foo}}</button>
controller:
$scope.foo = 1;
$scope.incrementFoo = function() {
++$scope.foo;
};
Upvotes: 1
Reputation: 4115
First of all, you should not use jQuery that way. Instead of selecting button with jQuery, you can just inject it to your directive using element parameter.
Second, you need to use $scope.$apply to trigger watches in your directive and controller.
app.directive('buttonTest', function() {
return {
scope: {
buttonSettings: '='
},
link: function(scope, element) {
element.bind('mouseover', function() {
scope.$apply(function() {
scope.buttonSettings.val++;
});
})
}
}
});
Check out this working plunker.
Upvotes: 1