Reputation: 157
I am trying to update a data stored in a controller (this.isUploaded) from a directive (I want to bind the update to an action on a DOM element (in this example, on a click, in my application, on a file upload through drag drop)). Based on what I read, the best way to do it is to inject a service which would act as a brdige between the two parts of the application with a data binding. The whole code I use is the following (inspired from this post, which do not work with directives) :
<body>
<div ng-controller="navController as navCtrl">
<p>isUploaded: {{navCtrl.isUploaded}}</p>
<div test-view></div>
</div>
</body>
And for the JavaScript:
angular.module('testApp', [])
.directive('testView', ['CreateBindingService', function(createBindingService) {
return {
restrict: 'EA',
template: '<a href="#">Incrementation</a>',
link: function(scope, element, attrs) {
element.bind('click', function(e) {
createBindingService.incrementIsUploaded();
console.log(createBindingService.getIsUploaded());
});
}
};
}])
.factory('CreateBindingService', function() {
var isUploaded = 1;
return {
getIsUploaded: function() {
return isUploaded;
},
incrementIsUploaded: function() {
isUploaded++;
return isUploaded;
}
};
})
.controller('navController', ['CreateBindingService', function(createBindingService) {
this.isUploaded = createBindingService.getIsUploaded();
}]);
The log does behave as expected (each click on the increment changes the value stored in the service), but the value in the model is not updated.
I tried to have a look at $watch, but so far, nothing really happens, so it seems to be more of a binding problem than an update one.
Could it be because of my use of this.isUploaded instead of $scope.isUploaded? Indeed, most of the posts I've seen uses of the latter, while I use the former (I learnt the basis of Angular on Code School, where they don't use $scope).
I do know that there are simpler ways to do it (in this context, it's obious, and even my "fancy" drag and drop file upload thing could probably be replaced by a way simpler directive. However, I still think that getting an answer to my question would help me to better understand how Angular works.
But if, you suggest a fundamentally different way to tackle the problem, I'm interested :)
Upvotes: 0
Views: 258
Reputation: 16498
It seems that bind event ours outside Angular scope so you can use it scope.$apply inside your directive. And change isUploaded to complex type please see demo below.
angular.module('testApp', [])
.directive('testView', ['CreateBindingService',
function(createBindingService) {
return {
restrict: 'EA',
template: '<a href="#">Incrementation</a>',
link: function(scope, element, attrs) {
element.bind('click', function(e) {
scope.$apply(function() {
createBindingService.incrementIsUploaded();
console.log(createBindingService.getIsUploaded());
});
});
}
};
}
])
.factory('CreateBindingService', function() {
var data = {
isUploaded: 1
};
return {
getIsUploaded: function() {
return data.isUploaded;
},
incrementIsUploaded: function() {
data.isUploaded++;
return data;
},
data: data
};
})
.controller('navController', ['CreateBindingService',
function(createBindingService) {
this.data = createBindingService.data;
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="testApp">
<div ng-controller="navController as navCtrl">
<p>isUploaded: {{navCtrl.data.isUploaded}}</p>
<div test-view></div>
</div>
</body>
Upvotes: 1