shimiz shimiz - 3 months ago 24
AngularJS Question

Parent isolated scope updated only once in Firefox

I’m trying to update parents scopes variables when

onchange
event is fired in a child custom directive.
The event I’m using in the child directive, which is an
input
file, is
onchange
that triggered by jqLite. That means,
operation outside Angular scope. For updating the scope I’m using
scope.$evalAsync
function (tried
$timeout
and
scope.$apply
as well). In the parents custom directives I’m using
$watch
function as the listener.

Please take a look in the jsfiddle full example

Markup

<div ng-app='myApp'>
<parent></parent>
</div>


Script

var myApp = angular.module('myApp', []);

myApp.directive('parent', function() {

return {
restrict: 'E',
template: '<div class="parent">Parent' + '<span class="file-name">{{selectedFileName}}</span>' + '<child files="files"></child>' + '</div>',
scope: {
files: '='
},
link: function(scope){
scope.$watch('files', function(newVal) {
if (newVal && newVal.length > 0) {
scope.selectedFileName = "selected file name: " + newVal[0].name;
}
});
}
};
});

myApp.directive('child', function() {

return {
restrict: 'E',
template: '<div class="child">Child<br />' + '<span class="file-name">{{selectedFileName}}</span>' + '<file-upload files="files"></file-upload>' + '</div>',
scope: {
files: '='
},
link: function(scope) {
scope.$watch('files', function(newVal) {
if (newVal && newVal.length > 0) {
scope.selectedFileName = "selected file name: " + newVal[0].name;
}
});
}
};
});

myApp.directive('fileUpload', function() {

return {
restrict: 'E',
template: '<input type="file" />',
scope: {
files: '='
},
link: function(scope, element) {
element.bind('change', function(e) {
scope.$evalAsync(function() {
scope.files = (e.srcElement || e.target).files;
});
});
}
};
});


In the example, every time I’m selecting new file, the parents scopes variable
files
are updated perfectly, and its
$watch
function are called.

The problem is that in Firefox the parents scopes
$watch
function is called only once. Only on the first time.


Thanks in advance

Answer

Solved.

Thanks to this post, which pointed me that the problem is that I’m using $watch.

According to the following explanation:

By default, $watch does not check for object equality, but just for reference

In my case I'm watching an array. The reference of it didn't change, and that's why the $watch function was not called. What actually changed, it's only the inner properties of the array. Therefore the solution is to use $watchCollection() instead, which:

Shallow watches the properties of an object and fires whenever any of the properties change ... ...for arrays this implies watching the array items

Why $watch is not working in Firefox, but working nicely in Chrome and IE? I still don't know.

Anyway, the bug resolved.