简体   繁体   English

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

[英]ngDialog not programmatically closing on IE but works on Chrome

I have a site that allows a person to import some data. 我有一个网站,允许一个人导入一些数据。 They click a button, and the file select opens and they select a file. 他们单击一个按钮,文件选择打开,他们选择一个文件。 When they select a file I open a dialog that they can't close that tells them their data is being imported. 当他们选择一个文件时,我打开一个他们无法关闭的对话框,告诉他们正在导入他们的数据。 Once I get the call back from the api call to import the file, I then close that dialog and open a new one that gives the status of the import. 一旦我从api调用中获取回调以导入文件,我就关闭该对话框并打开一个新的对话框,提供导入的状态。

On Chrome the "please wait while importing" dialog closes as expected. 在Chrome上,“请等待导入”对话框按预期关闭。 On IE it doesn't. 在IE上它没有。 If you use IE 11 it should happen in the following fiddle: 如果您使用IE 11,它应该在以下小提琴中发生:

http://jsfiddle.net/og6qsxdw/ http://jsfiddle.net/og6qsxdw/

You see a ghost like outline of the dialog go up and fade away like its trying to close but the dialog and overlay still remain. 你会看到像对话框轮廓一样的幽灵上升并逐渐消失,就像它试图关闭但对话框和叠加仍然存在。

<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 code: 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);
          });
        }
      }
    }
  }]);

Alright, so here's the deal. 好吧,所以这是交易。 In IE, when you open the dialog, two instances are instantiated. 在IE中,当您打开对话框时,将实例化两个实例。 When the upload completes, you have a reference to close the most recent dialog, but one existed milliseconds before as well. 上传完成后,您有一个关闭最近对话框的引用,但也有一个存在之前的毫秒。

I had originally thought at quick glance that this was just an ugly IE bug, and you had to "keep track" of the instances, however, I failed to take note of jQuery's involvment in your link function. 我原本以为快速浏览一下,这只是一个丑陋的IE漏洞,而且你必须“跟踪”实例,但是,我没有注意到jQuery在你的链接功能中的参与。 Thusly, my initial solution was a hack/workaround, but better can be done. 因此,我最初的解决方案是黑客/解决方法,但可以做得更好。

It seems that the mixture of the two libraries is the culprit, where Angular and jQuery are not communicating properly. 似乎两个库的混合是罪魁祸首,Angular和jQuery没有正确通信。 I've inserted a reference below to a ticket that discusses jQuery events with Angular. 我在下面的参考中插入了一个参考文章,讨论了使用Angular的jQuery事件。

jQuery and AngularJS: Bind Events to Changing DOM jQuery和AngularJS:将事件绑定到更改DOM

Solution

My suggestion, as always in these cases, is not to leverage jQuery on top of Angular. 在这些情况下,我的建议是不要在Angular之上利用jQuery。 It adds an additional layer of confusion, and requires you to be prudent about maintaining proper coupling between the two (in circumstances such as this). 它增加了一层混乱,并要求你谨慎保持两者之间的正确耦合(在这种情况下)。

I have provided a solution, where I clean up your link function. 我提供了一个解决方案,我清理你的链接功能。 It uses a lot of your existing code, but with the absence of the jQuery bits. 它使用了很多现有代码,但缺少jQuery位。 It seems to work just fine for me in both Chrome and IE now. 它现在在Chrome和IE中对我来说似乎都很好。

http://plnkr.co/edit/6Z4Rzg1Zm3w5rYyqQqmg?p=preview 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...");
          });

        }
      }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM