Angular.js: soporte de entrada [tipo = archivo] enlace

Creado en 18 sept. 2012  ·  145Comentarios  ·  Fuente: angular/angular.js

hola tratando de hacer una carga de archivo simple :) pero la entrada de type = file no parece vincularse.He intentado hg-model-instant pero no obtengo nada, incluso actualizado a 1.0.2 y nada

forms moderate not core feature

Comentario más útil

Esta solución depende de la implementación del lector de archivos:

...
.directive('file', function() {
    return {
        restrict: 'E',
        template: '<input type="file" />',
        replace: true,
        require: 'ngModel',
        link: function(scope, element, attr, ctrl) {
            var listener = function() {
                scope.$apply(function() {
                    attr.multiple ? ctrl.$setViewValue(element[0].files) : ctrl.$setViewValue(element[0].files[0]);
                });
            }
            element.bind('change', listener);
        }
    }
});

<file name="image" ng-model="inputFile" accept="image/png,image/jpg,image/jpeg" />

Luego tienes que hacer algunas cosas xhr tú mismo, pero creo que esto está fuera del enlace de la interfaz gráfica de usuario y más lógica de procesamiento.

y si te falta imaginación:

var file = $scope.inputFile;
$http.put('http://localhost:5984/demo/d06917e8d1fae1ae162ea7773c003f0b/' + file.name + '?rev=4-c10029f35a5c5ed9bd8cc31bf8589d3c', file, { headers: { 'Content-Type' : file.type } });

Esto funciona debido a xhr2 (http://www.html5rocks.com/en/tutorials/file/xhr2) y disculpe el largo ejemplo de URL de carga, es un punto final de documento couchdb (archivo adjunto).

Todos 145 comentarios

No hay un enlace predeterminado proporcionado por angular a input type = file.

Pero luego, la entrada del archivo es solo real para javascript, el único beneficio que podría ayudar tal enlace es borrar la entrada del archivo. (Angular tampoco proporciona soporte de marco para la carga de archivos ajax en este momento, creo)

@coli :

Tendría sentido poder capturar el evento onchange en la entrada [archivo].

En https://github.com/lgersman/jquery.orangevolt-ampere tenemos exactamente ese escenario: carga de archivos a través de XMLHTTPRequest V2.
Por lo tanto, implementamos nuestra propia directiva para capturar eventos de cambio de [archivo] de entrada para que las cargas de archivos se realicen sin recargar la página.

¡Me encantaría ver esa característica en angularjs!

¿Se ha realizado algún progreso con la vinculación a una entrada de archivo de tipo? He estado buscando una solución y parece que no puedo encontrar una que funcione ...

mi solución fue solo Ajax en lugar de solicitud o http.post

Enviado desde mi iPad

El 1 de marzo de 2013, a las 7:16 p. M., "Jgoldber" < [email protected] [email protected] > escribió:

¿Se ha realizado algún progreso con la vinculación a una entrada de archivo de tipo? He estado buscando una solución y parece que no puedo encontrarla.

-
Responda a este correo electrónico directamente o véalo en Gi

La mejor solución que encontré: http://jsfiddle.net/marcenuc/ADukg/49/. Comparta si encuentra una solución mejor.

Sí, esto realmente necesita ser analizado; poder seleccionar y cargar un archivo es bastante crucial para la mayoría de las aplicaciones web, por lo que admitir esta entrada es una característica que falta bastante obviamente.

Protuberancia. Esto debe agregarse a un hito.

Otro grito en apoyo de esto.

El archivo ng-model podría establecer el valor de un archivo desde la API de archivos HTML5, existen polyfills Flash y Silverlight para IE8 / IE9

Sí, establezca el valor en el archivo o en el elemento de entrada (que contiene la referencia al archivo)

Esta solución depende de la implementación del lector de archivos:

...
.directive('file', function() {
    return {
        restrict: 'E',
        template: '<input type="file" />',
        replace: true,
        require: 'ngModel',
        link: function(scope, element, attr, ctrl) {
            var listener = function() {
                scope.$apply(function() {
                    attr.multiple ? ctrl.$setViewValue(element[0].files) : ctrl.$setViewValue(element[0].files[0]);
                });
            }
            element.bind('change', listener);
        }
    }
});

<file name="image" ng-model="inputFile" accept="image/png,image/jpg,image/jpeg" />

Luego tienes que hacer algunas cosas xhr tú mismo, pero creo que esto está fuera del enlace de la interfaz gráfica de usuario y más lógica de procesamiento.

y si te falta imaginación:

var file = $scope.inputFile;
$http.put('http://localhost:5984/demo/d06917e8d1fae1ae162ea7773c003f0b/' + file.name + '?rev=4-c10029f35a5c5ed9bd8cc31bf8589d3c', file, { headers: { 'Content-Type' : file.type } });

Esto funciona debido a xhr2 (http://www.html5rocks.com/en/tutorials/file/xhr2) y disculpe el largo ejemplo de URL de carga, es un punto final de documento couchdb (archivo adjunto).

Es posible hacer que esto funcione en IE8 / 9 combinando este FileReader Polyfill basado en flash https://github.com/Jahdrien/FileReader y este polyfill js FormData puro que se basa en FileReader https://github.com/francois2metz/ html5-formdata. _update_ Moxie es un mejor polyfill

Mi solución fue bastante incompleta, al menos tan incompleta como el jsfiddle anterior, donde se manipula el prototipo del controlador ...

En el controlador:

    $scope.updateImage = '(' + function () {
      alert('moo');
    }.toString() + ')();';

Ponga en cadena mi devolución de llamada onchange deseada y envuélvala en un cierre.

   <input type="file" name="image" onchange="{{updateImage}}" ng-model="image">

Insértelo en el DOM usando Angular

No es exactamente bonito, pero funciona en Webkit. No hice ninguna prueba de navegador cruzado.

Estoy en 1.0.5 y todavía está roto. Usamos el ejemplo de Jgoldber y lo modificamos un poco:
http://jsfiddle.net/ADukg/2589/

Este ejemplo solo funcionará para un controlador, por lo que si tiene varios controladores, cada uno con entradas de archivo, deberá realizar algunos cambios.

Todavía no lo he probado en IE, pero supongo (conociendo IE) que no funcionará.

Suponiendo que solo desea llamar a una función en su alcance que toma el elemento de entrada como argumento, esto es bastante sencillo de implementar en una directiva:

http://jsfiddle.net/neilsarkar/vQzKJ/

(modificado del jsfiddle anterior, gracias @programmist)

'use strict';

function filesModelDirective(){
  return {
    controller: function($parse, $element, $attrs, $scope){
      var exp = $parse($attrs.filesModel);

      $element.on('change', function(){
        exp.assign($scope, this.files);
        $scope.$apply();
      });
    }
  };
}

configuración:

angular.module(...).directive('filesModel', filesModelDirective)

uso:

<input type="file" files-model="someObject.files" multiple>

Solucione esto pronto.

Sigo teniendo problemas ... en algunas versiones funciona, pero de todos modos no es compatible

Dado que se debe llamar a 1.5.0 $ digest si está utilizando la solución alternativa onchange:

<input type="file" onchange="angular.element(this).scope().myController.uploadFile(this.files[0]); angular.element(this).scope().$digest();">

+1 para un mejor soporte en ng-change y la entrada / archivo. Caso de uso: como cargador de una imagen, me gustaría poder editar esa imagen (cambiar el tamaño y recortar) antes de cargarla para una visualización óptima. Implementación: busque la imagen (usando input / file) y en el evento onchange mueva el archivo al lienzo y edítelo con fabricjs. No puedo pensar en una implementación de cambio que no esté activada.

cztomsik: estoy en 1.0.7 y no puedo hacer que su solución funcione: la función de alcance (esto) se resuelve bien, pero no se puede encontrar el controlador, la función uploadFile aparece como miembro del alcance (esto).

Jugando, tengo una pequeña modificación en la técnica, que parece estar funcionando para mí (todavía no sé por qué tuve:

<input type = "file" name = "file" ng-model = "file" onchange = "invokeUploadFile (this)" />

var invokeUploadFile = function (that) {
angular.element (que) .scope (). uploadFile (que)
angular.element (ese) .scope (). $ digest ();
}

¿Podría proporcionar jsfiddle / plunker?
Gracias


    1. 2013 v 18:17, tb01923 [email protected] :

+1 para un mejor soporte en ng-change y la entrada / archivo. Caso de uso: como cargador de una imagen, me gustaría poder editar esa imagen (cambiar el tamaño y recortar) antes de cargarla para una visualización óptima. Implementación: busque la imagen (usando input / file) y en el evento onchange mueva el archivo al lienzo y edítelo con fabricjs. No puedo pensar en una implementación de cambio que no esté activada.

cztomsik: estoy en 1.0.7 y no puedo hacer que su solución funcione: la función scope (this) se resuelve bien, pero no se puede encontrar el controlador, la función uploadFile aparece como miembro del objeto scope (this) pero cuando quitar el controlador que obtengo

Error de referencia no detectado: uploadFile no está definido blah.js: 15
$ scope.uploadFile blah.js: 15
invokeScope blah.js: 4
onchange

-
Responda a este correo electrónico directamente o véalo en GitHub.

+1. Lo necesita para iniciar la carga de un archivo HTML5 cuando un usuario elige un archivo. Es fácil solucionarlo, pero espero que esto funcione.

+1. impleméntelo, no implementarlo no es totalmente intuitivo.

+1

+1

Vamos chicos ... ha pasado más de un año y angular 1.2.0 todavía no tiene enlaces de archivo de entrada ... No entiendo por qué no se está agregando la función? Ha habido algunas buenas soluciones para la implementación. Me gustaría recibir una respuesta de un miembro del equipo angular sobre el tema, por favor.

Solo para citar una de las mejores soluciones (sé que es un enlace de datos de una forma, pero aún así es mejor que nada, la validación y la actualización del modelo funcionan incluso en IE7):

Definición

  /**
   * <strong i="8">@ngdoc</strong> inputType
   * <strong i="9">@name</strong> angular.module.ng.$compileProvider.directive.input.file
   *
   * <strong i="10">@description</strong>
   * HTML file input field.
   *
   * <strong i="11">@param</strong> {string} ngModel Assignable angular expression to data-bind to.
   * <strong i="12">@param</strong> {string} multiple Allows multiple files selection.
   * <strong i="13">@param</strong> {string=} name Property name of the form under which the 
                                control is published.
   *
   * <strong i="14">@example</strong>
      <doc:example>
        <doc:source>
         <script>
           function Ctrl($scope) {
           }
         </script>
         <form name="myForm" ng-controller="Ctrl">
           file: <input type="file" ng-model="file"> single file selection.<br/>
           files: <input type="file" ng-model="files" multiple> multi-file selection.<br/>
           <tt>file.name = {{file.name}}</tt><br/>
           <tt>files.length = {{files.length}}</tt><br/>
          </form>
        </doc:source>
        <doc:scenario>
          it('should change state', function() {
            expect(binding('file.name')).toBeUndefined();

            input('file').select('a file name');
            expect(binding('file.name')).toEqual('a file name');
          });
        </doc:scenario>
      </doc:example>
   */
  'file': fileInputType,

Función

function fileInputType(scope, element, attr, ctrl) {
  element.bind('change', function() {
    scope.$apply(function() {
      var files = element[0].files,
          isValid = true;

      if (msie < 10) {
        files = [element[0].value];
      }

      if (attr.accept) {
        var i, j, acceptType, fileType,
            types = map(attr.accept.split(','), function(t) { return trim(t).split('/'); });
        for (i = 0; i < files.length && isValid; ++i) {
          fileType = files[i].type.split('/');
          isValid = false;
          for (j = 0; j < types.length && !isValid; ++j) {
            acceptType = types[j];
            isValid = acceptType[0] === fileType[0] && (acceptType[1] === '*' || acceptType[1] === fileType[1]);
          }
        }
      }
      ctrl.$setValidity('file', isValid);

      var viewValue;
      if (isValid) viewValue = attr.multiple ? files : files[0];
      ctrl.$setViewValue(viewValue);
    });
  });
}

+1

+1

@ntrp ¿Por qué no

Ese cambio necesita ser elaborado un poco y probado, no tengo tiempo de momento para hacerlo.

+1

+1

-1: cara de troll:

Bromeando +1

+1

+1

+1

+1

+1

input [type = file] no es realmente un enlace bidireccional, a menos que usemos explícitamente la API de archivos, que no está disponible en todos los navegadores de destino. Agregar esto a ng-model no tiene mucho sentido, pero hay muchos complementos que admiten algunas variaciones de esta funcionalidad. ¿No estamos de acuerdo con delegar esto a los complementos por un tiempo?

http://caniuse.com/fileapi

@caitp Correcto, pero tiene sentido poder vincularse al evento de cambio, a través de ng-change, que no funciona.

Otra cosa que no funciona es la validación de formularios. Creo que el soporte de archivos debe implementarse para los nuevos navegadores con un respaldo de enlace de datos unidireccional para los antiguos. Si esta solución no es viable, en mi opinión, debería indicarse claramente en la wiki por qué no se implementa la funcionalidad y cómo resolver los problemas que causa esta falta de soporte. Recuerdo perder mucho tiempo antes de resolver mis necesidades de archivos de entrada cuando los usé por primera vez.

La cuestión es que los nombres de archivo no están vinculados a un modelo y, en realidad, no tendría sentido vincularlos a un modelo. Todas las propiedades de la interfaz de archivo son de solo lectura y la interfaz de FileList es solo una colección de archivos. No hay capacidad para enlace bidireccional, por lo que no hay una razón real para usar ng-model para estos en primer lugar. En su lugar, es bastante simple vincularse al evento change , y puede escribir fácilmente una directiva para agregar esa funcionalidad de modo que pueda usarla declarativamente si la necesita.

Pero, ¿cómo tiene sentido hacer que esto sea parte de ng-model cuando no tiene la capacidad de seguir el comportamiento del ng-model?

No hay ninguna razón por la que uno no pueda crear una interfaz personalizada para archivos, y angular puede hacer esto en algún momento, pero en mi opinión no tiene sentido con ng-model. No sé qué piensan los otros desarrolladores sobre esto, pueden estar de acuerdo o no. Pero desde mi perspectiva, una directiva separada tendría más sentido, porque input [type = file] simplemente no encaja en ng-model

  • Nada sobre el valor de la entrada de un archivo se puede escribir desde un contexto de script
  • No tenemos una forma real de realizar la validación aquí sin la API de archivos (que no es compatible con varios navegadores de destino), el navegador lo hace por nosotros, esencialmente. --- con la excepción de ngRequired validation

Lo único que realmente podríamos hacer para input [type = file] es $ setViewValue cuando el valor cambia (lo que realmente no tiene sentido), y de alguna manera cambiar ngModel para ignorar los cambios en el valor del modelo causados ​​por un cambio de script (o básicamente simplemente desactive el $ watch por completo). En cuanto a la validación, todo lo que realmente podemos admitir es ng-required, quiero decir, ¿qué más podemos hacer allí?

Me gustaría poder admitir una entrada de archivo con ngModel también, pero no veo cómo funcionaría, simplemente no encaja en la interfaz ngModel.

Estoy de acuerdo con esta afirmación, pero luego, como dije antes, necesitamos más énfasis en esto en la wiki o en general en la documentación para que los desarrolladores sepan lo que deben hacer para lograr la funcionalidad que necesitan.

@ntrp bueno, los parches de documentos son más que bienvenidos, y estaré encantado de revisarlos si envían uno :)

¿Puede ser una solución agregar una directiva específica en angular?

Estoy de acuerdo con la afirmación anterior, pero parece al menos un poco extraño que un
marco como angular no tiene una forma clara y limpia de lograr
esta...
Esto probablemente fue lo más desorientador que tuve que enfrentar al intentar
cargar un archivo...

Ah, ok @caitp , leí hace algún tiempo que la solicitud de extracción de wiki no estaba siendo evaluada activamente, así que no me molesté en contribuir. Si tengo algo de tiempo libre pronto contribuiré con mucho gusto :) gracias.

No me di cuenta de que la directiva ngChange requería que ngModel también estuviera presente, y supongo que es por eso que hay tanta discusión sobre ngModel aquí (y es por eso que obtengo este error ). Estoy de acuerdo en que el enlace bidireccional en una entrada [tipo = archivo] no tiene sentido.

Pero, ¿cuál es la razón exacta por la que ngChange requiere ngModel? En mi opinión, tiene mucho sentido poder vincularse al evento de cambio de un campo de entrada [tipo = archivo], digamos si desea enviar automáticamente el formulario una vez que se elige un archivo. En tal caso, realmente no me importa cuál sea el valor del campo. Solo me importa que haya cambiado. La mejor manera que he encontrado para manejar tal cosa es a través de la solución mencionada anteriormente por @cztomsik :

onchange="angular.element(this).scope().fileChangedHandler()"

Y esa no parece ser la mejor solución.

ng-change , a pesar de tener un nombre similar al de las otras directivas del controlador de eventos, no es en realidad un controlador para el evento change . Simplemente agrega un $viewChangeListener al ngModelController, que se activa cada vez que se llama a $setViewValue .

Estoy de acuerdo que es un nombre desafortunado

Este es un engaño de # 1236 que se cerró con este comentario: https://github.com/angular/angular.js/issues/1236#issuecomment -29115377

a menos que veamos una propuesta sobre cómo implementar esto para que sea liviano, pero funcional y no requiera forzar un estilo ux en los usuarios de framewok, lo consideraremos. Pero en este momento, creemos que los problemas de carga de archivos son lo suficientemente complejos como para que se resuelva como un módulo separado, probablemente fuera del núcleo.

+1

@IgorMinar echa un vistazo aquí, un poco sucio, pero muy interesante ejemplo de implementación: https://github.com/danialfarid/angular-file-upload. @danialfarid está haciendo un gran progreso con esto.

Compruebe cómo es un problema para todos, varios temas abiertos con varios comentarios. Debe proporcionarnos un módulo ngUpload: smile : https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills#file -api a http://docs.angularjs.org/guide /es decir.

¿Cómo estás pensando en solucionarlo?

+1

+1

+1

+1

+1

+1

+1

+1

Vaya, es un poco vergonzoso en esta etapa.

+1

No es realmente posible tener enlaces bidireccionales para las entradas de archivos, ciertamente cuando los navegadores de destino no son compatibles con la API de archivos (http://caniuse.com/fileapi) --- Pero incluso cuando pueden, input[type=file] realmente no encaja en eso de todos modos. Encuadernación bidireccional allí es realmente imposible

Lo siento, pero esto es más un problema / característica de seguridad de la plataforma web que cualquier otra cosa. Si fuera factible, se haría

@caitp Entiendo totalmente lo que está diciendo, pero "esto es más un problema / característica de seguridad de la plataforma web que cualquier otra cosa" es una declaración un poco ridícula. El objetivo de los marcos es facilitar las deficiencias de los navegadores, las especificaciones web y varias inconsistencias. Este es ciertamente un lugar donde una advertencia para fileAPI es adecuada. Ahora hay soluciones, ¿por qué no incorporarlas?

Algo tan simple como un envoltorio para esto, por ejemplo, sería un comienzo.

Dada la dirección en la que se dirige Angular 2.0 (transpilando modismos angulares, no ECMA), no creo que las limitaciones de la "plataforma web" deban ser una preocupación.

@todos los demás: ¿Qué hace Ember en este caso?

Editar: eliminar "obligatorio" de la declaración de transpilación.

_Sólo una aclaración rápida ._ La creación de aplicaciones Angular 2.0 no requiere un lenguaje transpilado o modismos que no sean ECMA. Puede usar código ES5 simple sin problemas. Si desea compilar la fuente Angular 2.0, debe usar traceur para compilar. Naturalmente, puede usar traceur para crear sus propias aplicaciones y aprovechar las mismas funciones que estamos usando dentro de Angular, pero eso es completamente opcional. Disculpe si ha habido alguna confusión sobre ese punto en nuestros anuncios.

@EisenbergEffect Mi mal. Lo sabía y debería haberlo revisado mejor. ¡Sin café!

Los marcos realmente no pueden sortear las limitaciones de la plataforma web. Por ejemplo, no podemos obligar al navegador a que nos permita escribir en atributos IDL de solo lectura (lo que realmente rompe el enlace bidireccional para los archivos), y no podemos obligar al navegador a exponernos el sistema de archivos, lo que realmente nos impide hacer algo interesante con eso

@caitp He estado siguiendo este problema desde hace algún tiempo. Creo que parece haber suficiente deseo de la comunidad de que Angular admita una entrada de selección de archivos simple. Actualmente (a menos que me equivoque), ¿crear una aplicación trivial que acepte un archivo y lo cargue a través de XHR usando Angular no tiene un patrón recomendado a seguir? Eso suena como una característica que merece al menos algo de atención aparte de "lo siento, no puedo hacerlo porque la vinculación bidireccional no tiene sentido aquí".

Quizás podamos reorientar esta conversación a "¿Cómo podría angular apoyar esto?" en lugar de "No encajará en nuestros patrones actuales".

La vinculación a la entrada del archivo es definitivamente posible, de hecho, lo hice en un proyecto anterior para AngularJS.

El hecho de que no pueda realizar un enlace bidireccional con las entradas de archivo es una característica de seguridad, y eso tiene sentido. Los autores nunca podrán establecer la ruta del archivo a través de un script, pero ¿por qué no enlazarlo en un solo sentido?

Seguro que rompe el paradigma, pero ¿a quién realmente le importa si eso significa que obtiene un ng-change y la capacidad de acceder a los archivos a través de la API de archivos sin hacks? jQuery puede vincularse a un evento de cambio en las entradas de archivo, ¿es la forma angular tan sagrada que no podemos vincularla dentro de un controlador? ¿Es una limitación técnica con la arquitectura o simplemente una barrera ideológica?

De acuerdo, estaba menos preocupado por el enlace bidireccional. Simplemente quería publicar el archivo con el resto de mi documento sin saltar por los obstáculos.

El 20 de mayo de 2014, a las 7:53 a. M., Justin Arruda < [email protected] [email protected] > escribió:

@c aitphttps: //github.com/caitp He estado siguiendo este problema durante algún tiempo. Creo que parece haber suficiente deseo de la comunidad de que Angular admita una entrada de selección de archivos simple. Actualmente (a menos que me equivoque), ¿crear una aplicación trivial que acepte un archivo y lo cargue a través de XHR usando Angular no tiene un patrón oficial a seguir? ¿No suena esto como una característica que merece al menos algo de atención aparte de "lo siento, no puedo hacerlo porque el enlace bidireccional no tiene sentido aquí"?

Quizás podamos reorientar esta conversación a "¿Cómo podría angular apoyar esto?" en lugar de "No encajará en nuestros patrones actuales".

-
Responda a este correo electrónico directamente o véalo en Gi

Luego tiene un caso en el que ng-model se comporta de manera muy diferente para un control de formulario en particular, y luego hay personas que presentan errores como "¿cómo es que el control de formulario envía el archivo incorrecto cuando cambio el valor a" foobarblah.txt "o lo que sea? API inconsistente -> malo.

ngModel no es totalmente ideal para estas cosas específicamente porque significa que tenemos un patrón específico en el que encajar, y es muy difícil para los autores de aplicaciones desactivarlo. Sin embargo, hay soluciones para esto en angular.dart y el prototipo v2.0.0, por lo que será mejor en el futuro. Pero realmente no podemos agregar otro comportamiento de ng-model que ignore todo lo que ng-model hace actualmente, no tendría sentido

acepta un archivo y lo carga a través de XHR usando Angular

@guruward, no podemos admitir esto en todos nuestros navegadores de destino para 1.x sin obligar a las personas a usar polyfills de ondas de choque o similares. Hay módulos de terceros que permiten esto y se pueden utilizar en su lugar. angular-file-upload envía las versiones nativas de shockwave polyfill y html5 simultáneamente, y elige la correcta. Por lo tanto, no es una mala solución, se recomienda encarecidamente si desea hacer esto.

Pero no estoy seguro de que sea algo que podamos poner en el núcleo, tendrías que preguntarle a Igor qué piensa de enviar un polyfill de ondas de choque en el núcleo.

No estoy diciendo que sea un caso de uso que la gente nunca querrá hacer, puedo entender que quiera hacer esto, simplemente estoy diciendo que no encaja en el patrón ngModel y requiere que agreguemos algo extra para poder admite todos los navegadores de destino, por lo que rompe el marco de esa manera.

¿Cuál es el daño de usar módulos de terceros para esto?

Este polyfill no requiere flash.

@jreading no es un polyfill, y solía enviarse con un cargador flash, probablemente todavía lo tenga en alguna parte.

Lo que está haciendo es confiar en la API de archivos, que no está disponible en todos los navegadores de destino y, por lo tanto, es problemático para el núcleo angular 1.x.

Sin esa API, no tiene forma de acceder al blob de archivos sin algo como una onda de choque.

Utiliza iframes en lugar de flash, es posible que esté pensando en esto . En lugar de discutir semántica, ¿qué tal una hoja de ruta? Comencemos con ng-change en la entrada de archivos para navegadores con capacidad de api de archivos.

@jreading desafortunadamente, esto no ayuda a los navegadores que no son compatibles con api, que incluye IE9, que aún es compatible. No podemos enviar una API que funcione en el navegador A compatible, pero no en el navegador B compatible en el núcleo sin ninguna solución para las personas que dependen del soporte de IE9. Y no, un iframe no expone el contenido de un archivo como un blob y lo hace descargable. Hnnggggg.

Existen soluciones para esto en módulos de terceros, que las aplicaciones pueden usar si creen que son adecuadas. Poner esto en el núcleo A) hace que esos módulos de terceros sean más difíciles, y B) no es compatible con todos los navegadores de destino, por lo que esto es un problema.

Esta es solo mi opinión, tal vez Igor o alguien más no esté de acuerdo, pero no creo que sea el enfoque correcto aquí.

¿Cuál es el daño de usar módulos de terceros si funcionan para usted y los necesita?

En realidad, nunca dio a entender que era necesario que un blob estuviera disponible para el controlador. Me arriesgo, pero el caso de uso más grande que veo es la capacidad de saber cuándo ha cambiado la entrada del archivo y la capacidad de enviarlo a un punto final de descanso, que está disponible con esta solución de iframe o API de archivo y angular hacks.

Los módulos de terceros son la única forma de realizar mejoras agresivas como la publicación de mi blog (¡¡sin carga para ti !!), pero podría dar la vuelta a la pregunta y preguntar "¿Qué hay de malo en tener una mejor API para los navegadores modernos?"

"¿Qué daño tiene tener una mejor API para los navegadores modernos?"

Este argumento es débil porque no toma en cuenta el costo de oportunidad; Hay muchas otras cosas en las que nosotros (el equipo central) podemos trabajar.

Lo suficientemente justo. Simplemente se siente como una gran brecha y fruta madura.

El problema aquí no se trata de cómo hacer que esto funcione con ngModel. Creo que ngModel podría exponer FileList desde el campo de entrada al alcance, pero en la otra dirección, solo permitiríamos configurar el modelo en nulo / indefinido para ser compatible. Los analizadores / formateadores probablemente no harían nada y los validadores simplemente harían cosas simples como verificar la presencia o ausencia de archivos.

El problema es (como se mencionó anteriormente) que sin el soporte de la API de archivos, hacer esto correctamente no es factible para el núcleo, dado que nuestra línea de base es IE9 y el relleno múltiple de estas cosas está fuera de discusión para el núcleo.

Además, tratar de manejar esta entrada de una manera que no sea compatible con todos los navegadores solo dificulta las soluciones de terceros, que ahora tienen que luchar / deshabilitar / solucionar la solución principal.

Las soluciones no centrales que manejan esto ya existen y se mencionaron en la discusión de este tema, así como en el número anterior.

Hay muchas otras cosas que tienen un mayor impacto que queremos hacer. Entiendo que este es un caso relativamente común, pero todavía no he escuchado por qué las soluciones existentes no son suficientes.

¿Podría reorientarse parte de la energía que se está poniendo en esta discusión para mejorar las soluciones existentes si lo necesitan, o crear una nueva solución que sea superior a las existentes?

Voy a cerrar esto como cerramos # 1236. Angular 2 se está construyendo para admitir navegadores modernos y con ese soporte de archivos estará fácilmente disponible.

Simplemente quiero saber cuándo ocurre el evento de cambio para poder acceder al elemento directamente y tomar la información del archivo y cargarlo a través de AJAJ.

@bjoshuanoah , ¿para qué necesitas ngModel? Simplemente vincule un detector de eventos a input = p

@caitp Quiero controlar todo en el controlador y no con una directiva.

Si pongo ng-change = "uploadFile ({$ event: $ event})"

Puedo tener $ scope.uploadFile (evento) en mi controlador. y manejarlo allí.

Mi caso de uso específico es este: subir archivo a s3, aplicar la URL a mi modelo.

en su lugar, tengo que irrumpir en el alcance para hacer lo mismo. Muy molesto:

<input name="highRes" scope="{{contentOptions.currentValue}}" key="value" type="file" onchange="angular.element(this).scope().setFile(this)">

Ojalá alguien matara este problema. para que todos podamos seguir adelante :)

El 25 de julio de 2014, a las 9:22 a. M., Brian < [email protected] [email protected] > escribió:

Simplemente quiero saber cuándo ocurre el evento de cambio para poder acceder al elemento directamente y tomar la información del archivo y cargarlo a través de AJAJ.

-
Responda a este correo electrónico directamente o véalo en Gi

+1

+1

+1000000000000000

+1

+1

+1

+1

+100500

+1
No estoy seguro de por qué Ajax es un problema. Es posible que desee cargar datos de un archivo csv en la máquina local en un modelo angular. Si ng-change funcionó en la entrada del archivo dentro de Angular, esto sería fácil, actualmente no lo es . Este escenario no requiere Ajax o una API de servidor en absoluto. Tampoco estoy seguro de por qué esto está cerrado.

Mi solución actual es hacer lo siguiente

 input(type="file", onchange="angular.element(this).scope().onFileSet(this.files)")

y en mi controlador solo tengo algo como

$scope.onFileSet = function(files) { 
// work your magic here 
}

Aunque apesta bastante, siento que estoy bastardizando angular como herramienta. Cualquier idea de cómo hacer esto de una manera más angular sería muy apreciada.

:Corazón corazón:

Aquí hay un velero: velero:

@samccone ¿No está el alcance () no disponible cuando el modo de depuración está desactivado?

@geetsce Eso es correcto (en 1.3.xy posterior)

bien, en 1.2 tierra todo está bien.

@Narretz , ¿tienes una solución mejor?

Esto funciona para mí, está inspirado en https://jasonturim.wordpress.com/2013/09/01/angularjs-drag-and-drop

<input type="file" multiple="multiple" data-dbinf-on-files-selected="chooseAFunctionName(selectedFileList)">
<script>
/**Directive to propagate selected files from an HTML input element with type="file"
 * to the surrounding AngularJS controller.
 */
myApp.directive('dbinfOnFilesSelected', [function() {
    return {
        restrict: 'A',
        scope: {
              //attribute data-dbinf-on-files-selected (normalized to dbinfOnFilesSelected) identifies the action
              //to take when file(s) are selected. The '&' says to  execute the expression for attribute
              //data-dbinf-on-files-selected in the context of the parent scope. Note though that this '&'
              //concerns visibility of the properties and functions of the parent scope, it does not
              //fire the parent scope's $digest (dirty checking): use $scope.$apply() to update views
              //(calling scope.$apply() here in the directive had no visible effect for me).
            dbinfOnFilesSelected: '&'
        },
        link: function(scope, element, attr, ctrl) {
            element.bind("change", function()
            {  //match the selected files to the name 'selectedFileList', and
               //execute the code in the data-dbinf-on-files-selected attribute
             scope.dbinfOnFilesSelected({selectedFileList : element[0].files});
            });
        }
    }
}]);

myApp.controller('myController', ['$scope', function($scope) {
    $scope.chooseAFunctionName = function (filelist) {
        for (var i = 0; i < filelist.length; ++i) {
            var file = filelist.item(i);
            //do something with file; remember to call $scope.$apply() to trigger $digest (dirty checking)
            alert(file.name);
           }
    };
}]);
</script>

+1

+1

No sucederá ... Déjalo ir, déjalo ir ...

+1

Como dijo @samccone ,

input(type="file", onchange="angular.element(this).scope().onFileSet(this.files)")

Esta no es la forma angular de hacer las cosas. Es extraño.

+1

+1

+1

Hola @caitp @Narretz, si ustedes quisieran que pudiera trabajar en un PR para esto para la rama 1.2x, avíseme si esto es algo que desea agregar o no. Entiendo las preocupaciones de seguridad y la falta de compatibilidad entre navegadores en lo que respecta a obtener acceso al objeto de archivo real, sin embargo, parece que el soporte básico para detectar cuándo ha cambiado la entrada de un archivo (pasando el evento original) proporcionaría suficiente gancho para que la gente haga su magia.

Gracias de nuevo por todo lo que haces: palm_tree:

+1

+1

+1

+1

+1

ng-file-upload está funcionando muy bien.

+1 para @neokyol !! ¡Funciona muy bien!

esta característica común debe estar por defecto en el marco

servicial

+1

+1

+1

+1

+1

esto funcionó para mí, puede ayudar

angular.module('app', [])
  .controller('MainCtrl', MainCtrl)
  .directive('fileChange', fileChange);

  function MainCtrl($scope) {
    $scope.upload = function () {
      // do something with the file
      alert($scope.file.name);
    };
  }

  function fileChange() {
    return {
      restrict: 'A',
      require: 'ngModel',
      scope: {
        fileChange: '&'
      },
      link: function link(scope, element, attrs, ctrl) {
        element.on('change', onChange);

        scope.$on('destroy', function () {
          element.off('change', onChange);
        });

        function onChange() {
          ctrl.$setViewValue(element[0].files[0]);
          scope.fileChange();
        }
      }
    };
  }
<div ng-app="app" ng-controller="MainCtrl">
  <input type="file" file-change="upload()" ng-model="file">
</div>

http://plnkr.co/edit/JYX3Pcq18gH3ol5XSizw?p=preview

+1

+1

+1

+1

+1000000000000000000000000

+1

+1

@dciccale , ¿puede proporcionar un ejemplo de plunker?

+1

+1

+1 Debería haber una directiva incorporada en la biblioteca principal para esto. Es bastante ridículo

+1

+1
¿Está programada la función para uno de los próximos lanzamientos?

+1

+1

Cómo hacerlo en proyectos donde $ scope nunca se inyecta en el controlador. Estoy usando laravel angular que usa la forma GULP y ES6 de declarar controladores.

es decir

class TestController{
    constructor(API){
        'ngInject';
        this.API = API
    }

    $onInit(){
        this.file = null;
    }
    upload() {
        console.log(this.file)
    }
    fileChanged(elm) {
        console.log('hey')
        this.file = elm.file;
        this.$apply();
    }
}

export const TestComponent = {
    templateUrl: './views/app/components/test/test.component.html',
    controller: TestController,
    controllerAs: 'vm',
    bindings: {}
}

Encontré un trabajo alrededor, creo. http://stackoverflow.com/questions/38449126/how-to-set-up-ng-file-upload-in-laravel-angular-project/38486379#38486379

+1

@ntrp @guruward @coli @lgersman @jgoldber @Siyfion
¿Cómo corrigió la validez de
Mi validación:
this.catalougeForm = this.catalougeFormBuilder.group ({
catalougeIconName: ['', Validators.required]
});
HTML:
(cambio) = "changeListener ($ evento)">

Mi validador está considerando el valor de catalougeIconName como vacío / nulo después de cargarlo.
Se está enviando la imagen, pero el validador no funciona

¿Alguna actualización sobre esto?

Alguna actualización ?

¿Fue útil esta página
0 / 5 - 0 calificaciones