I have a file upload directive that fires events (through scope.$emit) while the file is being uploaded that is then caught in my controller (through scope.$on) to update a progress bar. The file upload directive gets ng-switch-ed out so the user can fill in other information about the file while the file is being uploaded. I want the progress bar to keep getting updated while they're doing this. This was all working just fine with version 1.0.2, but it seems to be broken now in 1.0.4.
The jsFiddle I created is greatly simplified, but it shows the problem. When the page first loads, the event is fired from the directive and it gets caught in the controller and everything gets updated as expected. However, if you change the dropdown so that the directive gets ng-switch-ed out, the event stops getting caught. If you look in the console, the event is still gettting $emit-ed, but the controller just stops catching it. Even if I put the $on on the $rootScope(http://jsfiddle.net/uysAM/1/), it still has the same problem. If the event is still being $emit-ed, why would the scopes stop catching it?
If you change the src in the <script> tag at the top to use 1.0.2, it works just fine. Is this some new bug with the latest version? Thanks for any help.
This is a scope problem. Here is how I understand it.
The scope chain when foo=1
The scope chain is intact and we can catch the emitted event without problem.
The scope chain changes when foo=2
The scope chain is no longer intact. The emitted event doesn't propagate past myDirective's cleaned up parent scope. It is possible that this cleanup was added as a feature in 1.0.4.
Here is my solution to the problem. I use a fileLoader service to share state between the directive and the controller.http://jsfiddle.net/apBZX/
var myApp = angular.module("myApp", [])
myApp.controller('MyCtrl', function ($scope, $rootScope, fileLoader) {
$scope.$watch(function () {
return fileLoader.numberOfloadedFiles;
}, function (numberOfLoadedFiles) {
$scope.numberOfLoadedFiles = numberOfLoadedFiles;
});
$scope.foo = 1;
});
myApp.directive("myDirective", function (fileLoader) {
return {
restrict: 'A',
replace: true,
scope: {},
template: '<div>I am the directive</div>',
link: function (scope, element, attrs) {
if (!fileLoader.isLoading) {
fileLoader.loadFiles(scope);
}
}
}
});
myApp.service("fileLoader", function () {
return {
numberOfloadedFiles: 0,
isLoading: false,
loadFiles: function (scope) {
var self = this;
setInterval(function () {
scope.$apply(function(){
self.numberOfloadedFiles++;
});
}, 1000);
self.isLoading = true;
}
};
});