我正在尝试在子自定义指令中触发onchange
事件时更新父范围变量。
我在child指令中使用的事件是input
文件,由jqLite触发onchange
。那意味着,
在角度范围之外的操作。要更新范围,我正在使用scope.$evalAsync
函数(已尝试$timeout
和scope.$apply
)。在父母自定义指令中,我使用$watch
函数作为监听器。
请查看jsfiddle完整示例
标记
<div ng-app='myApp'>
<parent></parent>
</div>
脚本
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;
});
});
}
};
});
在示例中,每次我选择新文件时,父范围变量files
都会完美更新,并调用其$watch
函数。
问题是在Firefox中,父级范围$watch
函数只调用一次。仅在第一次。
提前致谢
答案 0 :(得分:0)
<强>解决。强>
感谢这个post,它指出我的问题是我正在使用$watch
。
根据以下解释:
默认情况下,
$watch
不检查对象是否相等,只是为了 参考
就我而言,我正在观看一个阵列。它的引用没有改变,这就是为什么没有调用$watch
函数的原因。实际改变的是,它只是数组的内部属性。因此,解决方案是使用$watchCollection()
代替,其中:
浅看物体的属性并在任何时候发射 属性改变......对于数组,这意味着要观察数组项
为什么$watch
在Firefox中不起作用,但在Chrome和IE中运行良好?答案是关于文件输入change
事件的实现。 Firefox总是触发change
事件,即使向其上传相同的文件也是如此。这不 Chrome和IE中的行为。因此,Firefox显然在每个files
事件上保留相同的change
数组对象,并且仅更改其内部项。显然,Chrome和IE会在每个files
事件中创建新的change
对象,但在上传具有相同名称的文件时不会触发事件。