angularjs - upload使用 - ng2-file-upload




Angular:$在IE11中已经有了应用,但在FF和Chrome中没有 (4)

我得到了一个

<input type="file" id="aircraftList" name="aircraftList" file-upload multiple/>

绑定到一个指令

angular.module("app.directives").directive('fileUpload', function () {
    return {
        scope: true,
        link: function (scope, el, attrs) {
            el.bind('change', function (event) {
                scope.$emit("fileSelected", { files: event.target.files, field: event.target.name });
            });
        }
    };
});

我在一个控制器中捕获这个事件:

$scope.$on("fileSelected", function (event, args) {
        $scope.$apply(function () {
            switch (args.field) {
                case "aircraftList":
                    self.attachments.aircraftList = args.files;
                    break;
                default:
                    break;
            }
        });
    });

由于某些原因,这在Chrome和Firefox中运行得非常好,但在IE11中出现以下错误:

如果我不把$应用,铬不更新视图,但IE浏览器是。 如果我把$ apply,Chrome的工作完美,IE浏览器打破。

任何人都知道这是什么,为什么在这里出错?


我不知道为什么两个浏览器表现不一样。 但我知道摆脱这个错误,并使其工作

你已经使用了$ apply()。 如果得到$ rootScope:inprog错误,则意味着已经有一个摘要循环正在运行。 为了避免这个错误,在超时条件下包装你的$ apply函数。

喜欢这个,

$scope.$on("fileSelected", function (event, args) {
$timeout(function () {
$scope.$apply(function () {
        switch (args.field) {
            case "aircraftList":
                self.attachments.aircraftList = args.files;
                break;
            default:
                break;
        }
    });
  },500);
});

我希望这对你有用。


实际上,与IE11 JavaScript引擎相比, chromeFF JavaScript引擎速度非常快。

因此,当$scope.$on("fileSelected" )在$digest chromeFF被触发时,之前的$digest循环将在$scope.$apply的时间完成$scope.$apply被执行,因此没有错误,因为没有$digest周期运行在这个阶段,我们需要另一个$digest循环来更新视图的帮助$scope.$apply和没有这个,视图不会被更新。

由于IE在上述相同的情况下速度相对较慢, $scope.$apply正在抛出错误,因为当前有一个$digest循环正在运行。 因此,如果没有$scope.$apply ,那么在运行$digest循环的帮助下,视图将会被更新。

当我们使用$timeout作为其他用户说的时候,一旦当前$digest循环完成,并且确保用另一个$digest循环更新视图,它将开始执行。

希望它能澄清你:-)

$scope.$on("fileSelected", function (event, args) {
        $timeout(function () {
            switch (args.field) {
                case "aircraftList":
                    self.attachments.aircraftList = args.files;
                    break;
                default:
                    break;
            }
        });
    });

您可以通过先检查来应用范围

(!$scope.$$phase) ? $scope.$apply() : null;

如果它已经在进行,它将不适用范围。


首先,你正在执行$digest循环中调用$apply 。 Chrome / FF可能适合你,但这真的是你运气不佳的原因。 真的在这个你是在用户的PC性能的摆布。 无论何时发送事件,Angular始终会触发自己的$digest循环。 你的$scope.$emit将在这里触发$digest

虽然这里会遇到一些问题,但是将会把所有事情都捆绑在一起,并且会引起更多的问题。 通常情况下,除非您响应外部Angular触发的事件,否则不需要触发$digest循环。

您的指令file-uploader似乎太依赖于您的视图模型 - 它甚至告诉控制器它应该存储返回的数据的字段。请记住,这是控制器的工作! 我已经改变了一下你的代码,以确保不需要两个同时的$apply循环,这就消除了你的问题,并且还要整理一些代码。

我已经改变了指令,使用双向数据绑定,而不是通过rootcope发射事件 - 对性能和功能封装的巨大改进。

app.directive('testUploader', [function() {
    return {
        scope: {
            ngModel: '='
        },
        link: function(scope, el) {
            el.bind('change', function(event) {
                if (event.target.files && event.target.files.length > 0) {
                    angular.forEach(event.target.files, function (newFile) {
                        scope.ngModel.push(newFile);
                    });
                    scope.$apply();
                }
            });
        }
    };
}]);

这大大简化了现在不需要处理客户端事件的控制器 - 它只是在视图模型和服务器上的任何底层数据模型之间进行调解

app.controller("testctrl", ['$scope', function($scope) {    
    $scope.data = {
        aircraftList: []
    };
}]);

看到在这里工作的JSFiddle: https ://jsfiddle.net/z2yLad92/27/

希望这可以帮助。





file-upload