ngDialog 未以编程方式关闭 IE,但适用于 Chrome
ngDialog not programmatically closing on IE but works on Chrome
我有一个允许用户导入一些数据的站点。他们单击一个按钮,文件 select 打开,他们 select 一个文件。当他们 select 一个文件时,我打开一个他们无法关闭的对话框,告诉他们正在导入他们的数据。一旦我从 api 调用中收到导入文件的回电,我就会关闭该对话框并打开一个新对话框以显示导入状态。
在 Chrome 上,"please wait while importing" 对话框按预期关闭。在 IE 上它没有。如果你使用 IE 11,它应该发生在以下 fiddle:
你看到对话框的轮廓像幽灵一样上升并消失,就像它试图关闭一样,但对话框和叠加层仍然存在。
<div ng-controller="MyCtrl">
<input type="file" ng-simple-upload web-api-url="http://www.fakeresponse.com/api/?sleep=5" select-fn="importFileSelected" callback-fn="importDataComplete" />
<script type="text/ng-template" id="templateId">
<div>
Getting Data
</div>
</script>
</div>
JavaScript/AngularJS代码:
var myApp = angular.module('myApp', ['ngDialog', 'ngSimpleUpload']);
function MyCtrl($scope, $http, ngDialog) {
$scope.importDataComplete = function() {
$scope.dlg.close();
}
$scope.importFileSelected = function() {
$scope.dlg = ngDialog.open({
template: 'templateId',
className: 'ngdialog-theme-default',
closeByDocument: false,
showClose: false
});
}
}
angular.module('ngSimpleUpload', [])
.directive('ngSimpleUpload', [function() {
return {
scope: {
webApiUrl: '@',
callbackFn: '=',
selectFn: '=',
buttonId: '@'
},
link: function(scope, element, attrs) {
// if button id value exists
if (scope.buttonId) {
$('#' + scope.buttonId).on('click', function() {
// retrieves files from file input
var files = element[0].files;
// will not fire until file(s) are selected
if (files.length == 0) {
console.log('No files detected.');
return false;
}
Upload(files);
});
} else {
// original code, trigger upload on change
element.on('change', function(evt) {
var files = evt.__files_ || (evt.target && evt.target.files);
Upload(files);
// removes file(s) from input
$(this).val('');
});
}
function Upload(files) {
var fd = new FormData();
angular.forEach(files, function(v, k) {
fd.append('file', files[k]);
});
// this tell us the user clicked open instead of cancel so we can start our overlay
scope.selectFn();
return $.ajax({
type: 'GET',
url: scope.webApiUrl,
async: true,
cache: false,
contentType: false,
processData: false
}).done(function(d) {
// callback function in the controller
scope.callbackFn(d);
}).fail(function(x) {
console.log(x);
});
}
}
}
}]);
好的,这就是交易。在 IE 中,当您打开对话框时,会实例化两个实例。上传完成后,您有一个关闭最近对话框的引用,但在几毫秒之前也存在一个对话框。
我本来以为这只是一个丑陋的 IE 错误,你必须 "keep track" 个实例,但是,我没有注意到 jQuery 的参与在你的 link 函数中。因此,我最初的解决方案是 hack/workaround,但可以做得更好。
似乎两个库的混合是罪魁祸首,其中 Angular 和 jQuery 无法正常通信。我在下面插入了一张票据的参考,该票据讨论了 jQuery 与 Angular 的事件。
jQuery and AngularJS: Bind Events to Changing DOM
解决方案
在这些情况下,我的建议是不要在 Angular 之上利用 jQuery。它增加了一层额外的混乱,并要求您谨慎地保持两者之间的适当耦合(在这种情况下)。
我提供了一个解决方案,我在其中清理了您的 link 函数。它使用了大量您现有的代码,但缺少 jQuery 位。它现在在 Chrome 和 IE 中似乎对我来说都很好。
http://plnkr.co/edit/6Z4Rzg1Zm3w5rYyqQqmg?p=preview
link: function(scope, element, attrs) {
console.warn("Element is", element);
// original code, trigger upload on change
element.on('change', function(evt) {
var files = evt.__files_ || (evt.target && evt.target.files);
Upload(files);
});
function Upload(files) {
var fd = new FormData();
angular.forEach(files, function(v, k) {
fd.append('file', files[k]);
console.log("File loaded");
});
// this tell us the user clicked open instead of cancel so we can start our overlay
scope.selectFn();
$http({
url: scope.webApiUrl,
method: "GET",
cache: true
}).success(function(d, status, headers, config) {
scope.callbackFn(d);
}).error(function(data, status, headers, config) {
console.warn("Request failed...");
});
}
}
我有一个允许用户导入一些数据的站点。他们单击一个按钮,文件 select 打开,他们 select 一个文件。当他们 select 一个文件时,我打开一个他们无法关闭的对话框,告诉他们正在导入他们的数据。一旦我从 api 调用中收到导入文件的回电,我就会关闭该对话框并打开一个新对话框以显示导入状态。
在 Chrome 上,"please wait while importing" 对话框按预期关闭。在 IE 上它没有。如果你使用 IE 11,它应该发生在以下 fiddle:
你看到对话框的轮廓像幽灵一样上升并消失,就像它试图关闭一样,但对话框和叠加层仍然存在。
<div ng-controller="MyCtrl">
<input type="file" ng-simple-upload web-api-url="http://www.fakeresponse.com/api/?sleep=5" select-fn="importFileSelected" callback-fn="importDataComplete" />
<script type="text/ng-template" id="templateId">
<div>
Getting Data
</div>
</script>
</div>
JavaScript/AngularJS代码:
var myApp = angular.module('myApp', ['ngDialog', 'ngSimpleUpload']);
function MyCtrl($scope, $http, ngDialog) {
$scope.importDataComplete = function() {
$scope.dlg.close();
}
$scope.importFileSelected = function() {
$scope.dlg = ngDialog.open({
template: 'templateId',
className: 'ngdialog-theme-default',
closeByDocument: false,
showClose: false
});
}
}
angular.module('ngSimpleUpload', [])
.directive('ngSimpleUpload', [function() {
return {
scope: {
webApiUrl: '@',
callbackFn: '=',
selectFn: '=',
buttonId: '@'
},
link: function(scope, element, attrs) {
// if button id value exists
if (scope.buttonId) {
$('#' + scope.buttonId).on('click', function() {
// retrieves files from file input
var files = element[0].files;
// will not fire until file(s) are selected
if (files.length == 0) {
console.log('No files detected.');
return false;
}
Upload(files);
});
} else {
// original code, trigger upload on change
element.on('change', function(evt) {
var files = evt.__files_ || (evt.target && evt.target.files);
Upload(files);
// removes file(s) from input
$(this).val('');
});
}
function Upload(files) {
var fd = new FormData();
angular.forEach(files, function(v, k) {
fd.append('file', files[k]);
});
// this tell us the user clicked open instead of cancel so we can start our overlay
scope.selectFn();
return $.ajax({
type: 'GET',
url: scope.webApiUrl,
async: true,
cache: false,
contentType: false,
processData: false
}).done(function(d) {
// callback function in the controller
scope.callbackFn(d);
}).fail(function(x) {
console.log(x);
});
}
}
}
}]);
好的,这就是交易。在 IE 中,当您打开对话框时,会实例化两个实例。上传完成后,您有一个关闭最近对话框的引用,但在几毫秒之前也存在一个对话框。
我本来以为这只是一个丑陋的 IE 错误,你必须 "keep track" 个实例,但是,我没有注意到 jQuery 的参与在你的 link 函数中。因此,我最初的解决方案是 hack/workaround,但可以做得更好。
似乎两个库的混合是罪魁祸首,其中 Angular 和 jQuery 无法正常通信。我在下面插入了一张票据的参考,该票据讨论了 jQuery 与 Angular 的事件。
jQuery and AngularJS: Bind Events to Changing DOM
解决方案
在这些情况下,我的建议是不要在 Angular 之上利用 jQuery。它增加了一层额外的混乱,并要求您谨慎地保持两者之间的适当耦合(在这种情况下)。
我提供了一个解决方案,我在其中清理了您的 link 函数。它使用了大量您现有的代码,但缺少 jQuery 位。它现在在 Chrome 和 IE 中似乎对我来说都很好。
http://plnkr.co/edit/6Z4Rzg1Zm3w5rYyqQqmg?p=preview
link: function(scope, element, attrs) {
console.warn("Element is", element);
// original code, trigger upload on change
element.on('change', function(evt) {
var files = evt.__files_ || (evt.target && evt.target.files);
Upload(files);
});
function Upload(files) {
var fd = new FormData();
angular.forEach(files, function(v, k) {
fd.append('file', files[k]);
console.log("File loaded");
});
// this tell us the user clicked open instead of cancel so we can start our overlay
scope.selectFn();
$http({
url: scope.webApiUrl,
method: "GET",
cache: true
}).success(function(d, status, headers, config) {
scope.callbackFn(d);
}).error(function(data, status, headers, config) {
console.warn("Request failed...");
});
}
}