tutorial ng2 formdata angularjs file-upload

angularjs - ng2 - Angular: $ aplica ya en progreso en IE11, pero no en FF y Chrome



upload file angular 6 (5)

tengo un

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

obligado a una directiva

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 }); }); } }; });

Capté este evento en un controlador:

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

Por alguna razón, esto funciona perfectamente en Chrome y Firefox, pero falla en IE11 con el siguiente error:

Si no pongo $ apply, Chrome no actualiza la vista, pero IE sí. Si pongo $, Chrome funciona perfecto y IE se rompe.

¿Alguien sabe qué y por qué sale mal aquí?


Puede aplicar el alcance al verificar primero

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

No aplicará alcance si ya está en progreso.


Usted se metió en este problema ya que su código intenta desencadenar el ciclo de resumen antes de que uno se haya completado y que esté enfrentando solo en IE probablemente debido a la naturaleza lenta de IE. entonces mi idea es usar $ scope. $ evalAsync

$scope.$evalAsync(function () { switch (args.field) { case "aircraftList": self.attachments.aircraftList = args.files; break; default: break; } });

$ scope. $ evalAsync agregará la función suministrada a una cola que será drenada al comienzo del siguiente ciclo en un ciclo de resumen.

Espero que esto funcione para ti.

Gracias


No sé por qué ambos navegadores se comportan de manera diferente. Pero sé que para deshacerse de este error y hacerlo funcionar

Usaste $ apply (). Si obtiene el error $ rootScope: inprog , significa que ya se está ejecutando un ciclo de resumen. Para evitar este error, ajuste su función $ apply en una condición de tiempo de espera excedido.

Me gusta esto,

$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); });

Espero que esto funcione para ti.


En realidad, los motores de JavaScript chrome y FF son muy rápidos en comparación con el motor de JavaScript IE11 .

Por lo tanto, cuando $scope.$on("fileSelected" se activa en chrome & FF , el bucle $digest anterior se completará en el momento de $scope.$apply Se ejecuta $scope.$apply y, por lo tanto, no hay errores. Como no hay $digest ciclo se está ejecutando en esta etapa, necesitamos otro $digest ciclo de $digest para actualizar la vista con la ayuda de $scope.$apply y sin esto, la vista no se actualizará.

Como IE es comparativamente lento en el mismo escenario anterior, $scope.$apply arroja un error ya que hay un bucle $digest está ejecutando actualmente. Por lo tanto, sin $scope.$apply , La vista se actualizará con la ayuda del ciclo $digest actual.

Cuando usamos $timeout como dicen otros usuarios, se ejecutará una vez que se complete el ciclo actual de $digest y asegurándose de actualizar la vista con otro ciclo de $digest .

Espero que te aclare :-)

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


En primer lugar, está llamando a $apply desde un ciclo de $digest ya se está ejecutando. Chrome / FF puede estar bien para ti, pero eso depende de la suerte de tu parte. Realmente en esto estás a merced del rendimiento de la PC del usuario. Angular siempre activará su propio ciclo de $digest cuando esté transmitiendo eventos. Su $scope.$emit desencadenará $digest aquí.

Aquí tienes algunos problemas que van a atar todo en nudos y causarán más problemas de este tipo. Normalmente, no debería haber necesidad de activar un ciclo de $digest menos que responda a eventos desencadenados desde fuera de Angular.

Su carga de file-uploader directivas parece demasiado dependiente de su modelo de visualización, incluso le está diciendo al controlador en qué campo debe almacenar los datos devueltos. Recuerde, ese es el trabajo de los controladores. He cambiado un poco el código para asegurarme de que no hay necesidad de tener dos ciclos simultáneos de $apply , lo que elimina su problema y también ordena un poco el código.

Cambié la directiva para utilizar el enlace de datos bidireccional en lugar de emitir eventos a través del ramoscopio: gran mejora del rendimiento y encapsulación de la funcionalidad.

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

Esto simplifica enormemente el controlador que ahora no tiene necesidad de manejar eventos de clientes; simplemente media entre el modelo de vista y cualquier modelo de datos subyacente en su servidor.

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

Ver JSFiddle trabajando aquí: https://jsfiddle.net/z2yLad92/27/

Espero que esto ayude.