ngDialog没有以编程方式关闭IE,但适用于Chrome

use*_*521 8 angularjs ng-dialog

我有一个网站,允许一个人导入一些数据.他们单击一个按钮,文件选择打开,他们选择一个文件.当他们选择一个文件时,我打开一个他们无法关闭的对话框,告诉他们正在导入他们的数据.一旦我从api调用中获取回调以导入文件,我就关闭该对话框并打开一个新的对话框,提供导入的状态.

在Chrome上,"请等待导入"对话框按预期关闭.在IE上它没有.如果您使用IE 11,它应该在以下小提琴中发生:

http://jsfiddle.net/og6qsxdw/

你会看到像对话框轮廓一样的幽灵上升并逐渐消失,就像它试图关闭但对话框和叠加仍然存在.

<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>
Run Code Online (Sandbox Code Playgroud)

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);
          });
        }
      }
    }
  }]);
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 7

好吧,所以这是交易.在IE中,当您打开对话框时,将实例化两个实例.上传完成后,您有一个关闭最近对话框的引用,但也有一个存在之前的毫秒.

我原本以为快速浏览一下,这只是一个丑陋的IE漏洞,而且你必须"跟踪"实例,但是,我没有注意到jQuery在你的链接功能中的参与.因此,我最初的解决方案是黑客/解决方法,但可以做得更好.

似乎两个库的混合是罪魁祸首,Angular和jQuery没有正确通信.我在下面的参考中插入了一个参考,该论文讨论了使用Angular的jQuery事件.

jQuery和AngularJS:将事件绑定到更改DOM

在这些情况下,我的建议是不要在Angular之上利用jQuery.它增加了一层混乱,并要求你谨慎保持两者之间的正确耦合(在这种情况下).

我提供了一个解决方案,我清理你的链接功能.它使用了很多现有代码,但缺少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...");
          });

        }
      }
Run Code Online (Sandbox Code Playgroud)