Angular.js: UnterstĂŒtzung von input[type=file] Binding

Erstellt am 18. Sept. 2012  Â·  145Kommentare  Â·  Quelle: angular/angular.js

Hallo, ich versuche, einen einfachen Dateiupload durchzufĂŒhren :) aber die Eingabe von type=file scheint nicht zu binden. Ich habe hg-model-instant ausprobiert, aber nichts bekommen, sogar auf 1.0.2 aktualisiert und nichts

forms moderate not core feature

Hilfreichster Kommentar

Diese Lösung hÀngt davon ab, ob der Dateireader implementiert ist:

...
.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" />

Sie mĂŒssen dann einige xhr-Sachen selbst machen, aber ich glaube, dass dies außerhalb der GUI-Bindung und mehr Verarbeitungslogik liegt.

und wenn es dir an Phantasie mangelt:

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

Dies funktioniert wegen xhr2 (http://www.html5rocks.com/en/tutorials/file/xhr2) und bitte entschuldigen Sie die lange Beispiel-Upload-URL, es ist ein Couchdb-Dokumentendpunkt (Anhang).

Alle 145 Kommentare

Es gibt keine Standardbindung von angle an input type=file.

Aber dann ist die Dateieingabe nur fĂŒr Javascript real, der einzige Vorteil, den eine solche Bindung helfen könnte, besteht darin, die Dateieingabe zu löschen. (Angular bietet derzeit auch keine Framework-UnterstĂŒtzung fĂŒr den Ajax-Upload von Dateien, glaube ich)

@coli : Das ist nicht die ganze Wahrheit.

Es wÀre sinnvoll, das onchange-Ereignis bei input[file] abfangen zu können.

Unter https://github.com/lgersman/jquery.orangevolt-ampere haben wir genau dieses Szenario: Datei-Uploads ĂŒber XMLHTTPRequest V2.
Aus diesem Grund haben wir unsere eigene Direktive implementiert, um input[file] change-Ereignisse abzufangen, um Dateiuploads ohne Neuladen der Seite durchzufĂŒhren.

Ich wĂŒrde diese Funktion gerne in anglejs sehen!

Gab es Fortschritte bei der Bindung an eine Eingabe vom Typ Datei? Ich habe nach einer Lösung gesucht und finde keine funktionierende...

meine Lösung war nur Ajax statt Request oder http.post

Von meinem iPad gesendet

Am 1. MĂ€rz 2013 um 19:16 Uhr schrieb "jgoldber" < [email protected] [email protected] >:

Gab es Fortschritte bei der Bindung an eine Eingabe vom Typ Datei? Ich habe nach einer Lösung gesucht und finde keine.

—
Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf Gi tHub an

Beste Lösung, die ich gefunden habe: http://jsfiddle.net/marcenuc/ADukg/49/. Bitte teilen Sie, wenn Sie auf eine bessere Lösung stoßen.

Ja, das muss man sich wirklich ansehen; Die Möglichkeit, eine Datei auszuwĂ€hlen und hochzuladen, ist fĂŒr die meisten Webanwendungen von entscheidender Bedeutung, daher ist die UnterstĂŒtzung dieser Eingabe eine ziemlich offensichtliche fehlende Funktion.

Stoßen. Dies muss zu einem Meilenstein hinzugefĂŒgt werden.

Ein weiterer Ruf zur UnterstĂŒtzung dieser.

ng-model-Datei einen Wert auf eine Datei aus der HTML5-Datei-API setzen könnte, es gibt Flash- und Silverlight-Polyfills fĂŒr IE8/IE9

Ja, entweder setzen Sie den Wert auf die Datei oder auf das Eingabeelement (das einen Verweis auf die Datei enthÀlt)

Diese Lösung hÀngt davon ab, ob der Dateireader implementiert ist:

...
.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" />

Sie mĂŒssen dann einige xhr-Sachen selbst machen, aber ich glaube, dass dies außerhalb der GUI-Bindung und mehr Verarbeitungslogik liegt.

und wenn es dir an Phantasie mangelt:

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

Dies funktioniert wegen xhr2 (http://www.html5rocks.com/en/tutorials/file/xhr2) und bitte entschuldigen Sie die lange Beispiel-Upload-URL, es ist ein Couchdb-Dokumentendpunkt (Anhang).

Es ist möglich, dies in IE8/9 zum Laufen zu bringen, indem Sie diesen Flash-basierten FileReader Polyfill https://github.com/Jahdrien/FileReader und diesen reinen js FormData Polyfill kombinieren, der auf FileReader basiert https://github.com/francois2metz/ html5-Formdaten. _update_ Moxie ist ein besserer Polyfill

Meine Lösung war ziemlich skizzenhaft, mindestens so skizzenhaft wie die obige jsfiddle, mit der der Controller-Prototyp herumgefummelt wird ...

Im Controller:

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

Stringify meinen gewĂŒnschten Onchange-Callback und wickeln Sie ihn in einen Verschluss ein.

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

FĂŒgen Sie es mit Angular . in das DOM ein

Nicht gerade schön, aber es funktioniert in Webkit. Ich habe keine Cross-Browser-Tests durchgefĂŒhrt.

Ich bin auf 1.0.5 und es ist immer noch kaputt. Wir haben das Beispiel von Jgoldber verwendet und es ein wenig optimiert:
http://jsfiddle.net/ADukg/2589/

Dieses Beispiel funktioniert nur fĂŒr einen Controller. Wenn Sie also mehrere Controller haben, von denen jeder ĂŒber Dateieingaben verfĂŒgt, mĂŒssen Sie einige Änderungen vornehmen.

Habe es noch nicht auf dem IE getestet, aber ich vermute (mit dem IE), dass es nicht funktioniert.

Angenommen, Sie möchten nur eine Funktion in Ihrem GĂŒltigkeitsbereich aufrufen, die das Eingabeelement als Argument verwendet, ist dies ziemlich einfach in einer Direktive zu implementieren:

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

(geÀndert von der obigen jsfiddle, danke @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();
      });
    }
  };
}

Aufbau:

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

Verwendungszweck:

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

Bitte beheben Sie dies bald.

Habe immer noch Probleme.. in einigen Versionen funktioniert es, wird aber trotzdem nicht unterstĂŒtzt

Seit 1.5.0 muss $digest aufgerufen werden, wenn Sie den onchange-Workaround verwenden:

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

+1 fĂŒr bessere UnterstĂŒtzung bei der ng-Änderung und der Eingabe/Datei. Anwendungsfall: Als Uploader eines Bildes möchte ich dieses Bild vor dem Hochladen fĂŒr eine optimale Anzeige bearbeiten (GrĂ¶ĂŸe Ă€ndern und zuschneiden). Implementierung: Navigieren Sie zum Bild (mit Eingabe/Datei) und verschieben Sie die Datei beim onchange-Ereignis auf die Leinwand und bearbeiten Sie sie mit Fabricjs. Ich kann mir keine Implementierung ohne Änderung vorstellen.

cztomsik - Ich bin auf 1.0.7 und kann Ihre Lösung nicht zum Laufen bringen - die Funktion scope(this) wird gut aufgelöst, aber der Controller kann nicht gefunden werden, die Funktion uploadFile wird als Mitglied des scope(this) aufgefĂŒhrt.

Ich habe eine leichte Modifikation an der Technik, die fĂŒr mich zu funktionieren scheint (ich weiß immer noch nicht, warum ich die hatte:

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

var invokeUploadFile = Funktion (das) {
angle.element(das).scope().uploadFile(das)
angle.element(that).scope().$digest();
}

Könnten Sie jsfiddle/plunker bereitstellen?
Danke


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

+1 fĂŒr bessere UnterstĂŒtzung bei der ng-Änderung und der Eingabe/Datei. Anwendungsfall: Als Uploader eines Bildes möchte ich dieses Bild vor dem Hochladen fĂŒr eine optimale Anzeige bearbeiten (GrĂ¶ĂŸe Ă€ndern und zuschneiden). Implementierung: Navigieren Sie zum Bild (mit Eingabe/Datei) und verschieben Sie die Datei beim onchange-Ereignis auf die Leinwand und bearbeiten Sie sie mit Fabricjs. Ich kann mir keine Implementierung ohne Änderung vorstellen.

cztomsik - Ich bin auf 1.0.7 und kann Ihre Lösung nicht zum Laufen bringen - die Funktion scope(this) wird gut aufgelöst, aber der Controller kann nicht gefunden werden, die Funktion uploadFile wird als Mitglied des scope(this)-Objekts aufgefĂŒhrt, aber wenn ich Entfernen Sie den Controller, den ich bekomme

Uncaught ReferenceError: uploadFile ist nicht definiert blah.js:15
$scope.uploadFile blah.js:15
invokeScope blah.js:4
bei Änderung

—
Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an.

+1. Benötigen Sie es, um einen HTML5-Datei-Upload zu starten, wenn ein Benutzer eine Datei auswĂ€hlt. Es ist einfach zu umgehen, aber ich wĂŒrde erwarten, dass dies funktioniert.

+1. Bitte implementieren, nicht implementieren ist absolut nicht intuitiv.

+1

+1

Kommt schon, Leute.. es ist mehr als ein Jahr her und die eckige 1.2.0 hat immer noch keine Eingabedateibindungen... Ich verstehe nicht, warum das Feature nicht hinzugefĂŒgt wird? Es gab einige gute Lösungen fĂŒr die Umsetzung. Ich hĂ€tte gerne eine kantige Antwort eines Teammitglieds zu diesem Thema.

Um nur eine der besten Lösungen zu zitieren (ich weiß, es ist eine Einweg-Datenbindung, aber immer noch besser als nichts, Validierung und Modellaktualisierung funktionieren sogar im IE7):

Definition

  /**
   * <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,

Funktion

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 Warum veröffentlichst du diese Änderung nicht?

Diese Änderung muss noch ein wenig ausgearbeitet und getestet werden, dazu habe ich im Moment keine Zeit.

+1

+1

-1:Trollgesicht:

Scherz +1

+1

+1

+1

+1

+1

input[type=file] ist nicht wirklich eine 2-Wege-Bindung, es sei denn, wir verwenden explizit die Datei-API, die nicht in allen Zielbrowsern verfĂŒgbar ist. Es macht nicht viel Sinn, dies zu ng-model hinzuzufĂŒgen, aber es gibt viele Plugins, die einige Variationen dieser FunktionalitĂ€t unterstĂŒtzen. Ist es nicht in Ordnung, dies fĂŒr eine Weile einfach an Plugins zu delegieren?

http://caniuse.com/fileapi

@caitp Richtig, aber es ist sinnvoll, sich ĂŒber ng-change an das Änderungsereignis binden zu können, was nicht funktioniert.

Eine andere Sache, die nicht funktioniert, ist die Formularvalidierung. Ich denke, DateiunterstĂŒtzung sollte fĂŒr neue Browser mit Einweg-Datenbindungs-Fallback fĂŒr alte implementiert werden. Wenn diese Lösung nicht praktikabel ist, sollte meiner Meinung nach im Wiki klar angegeben werden, warum die FunktionalitĂ€t nicht implementiert ist und wie man die Probleme löst, die dieser fehlende Support verursacht. Ich erinnere mich, dass ich viel Zeit verloren habe, bevor ich meine Anforderungen an die Eingabedatei gelöst habe, als ich sie zum ersten Mal verwendet habe.

Die Sache ist die, Dateinamen sind nicht an ein Modell gebunden, und es wĂ€re nicht wirklich sinnvoll, sie an ein Modell zu binden. Jede Eigenschaft der File-Schnittstelle ist schreibgeschĂŒtzt, und die FileList-Schnittstelle ist nur eine Sammlung von Files. Es gibt keine KapazitĂ€t fĂŒr 2-Wege-Bindungen, daher gibt es keinen wirklichen Grund, ĂŒberhaupt ng-model dafĂŒr zu verwenden. Es ist einfach, stattdessen an das Ereignis change zu binden, und Sie können ganz einfach eine Direktive schreiben, um diese FunktionalitĂ€t hinzuzufĂŒgen, damit Sie sie bei Bedarf deklarativ verwenden können.

Aber wie ist es sinnvoll, dies zu einem Teil des ng-Modells zu machen, wenn es nicht die FĂ€higkeit hat, dem Verhalten des ng-Modells zu folgen?

Es gibt keinen Grund, warum man keine benutzerdefinierte Schnittstelle fĂŒr Dateien erstellen kann, und angle kann dies irgendwann tun, aber meiner Meinung nach macht es mit ng-model nicht wirklich Sinn. Ich weiß nicht, was die anderen Entwickler darĂŒber denken, sie können zustimmen oder nicht. Aber aus meiner Sicht wĂ€re eine separate Direktive sinnvoller, da input[type=file] einfach nicht ins ng-Modell passt

  • Nichts ĂŒber den Wert einer Dateieingabe kann aus einem Skriptkontext geschrieben werden
  • Wir haben hier keine wirkliche Möglichkeit, die Validierung ohne die File API (die in einigen Zielbrowsern nicht unterstĂŒtzt wird) durchzufĂŒhren, der Browser ĂŒbernimmt dies im Wesentlichen fĂŒr uns. --- mit Ausnahme der ngRequired-Validierung

Das einzige, was wir wirklich fĂŒr input[type=file] tun könnten, ist $setViewValue, wenn sich der Wert Ă€ndert (was nicht wirklich Sinn macht) und irgendwie ngModel so Ă€ndern, dass Änderungen am Modellwert ignoriert werden, die durch eine SkriptĂ€nderung verursacht wurden (oder im Grunde deaktivieren Sie einfach die $watch vollstĂ€ndig). Was die Validierung angeht, alles, was wir wirklich unterstĂŒtzen können, ist ng-erforderlich, ich meine, was können wir da noch tun?

Ich wĂŒrde gerne auch eine Dateieingabe mit ngModel unterstĂŒtzen, aber ich sehe nicht, wie das funktionieren wĂŒrde, es passt einfach nicht in die ngModel-Schnittstelle.

Ich stimme dieser Aussage zu, aber wie bereits erwĂ€hnt, mĂŒssen wir dies im Wiki oder allgemein in der Dokumentation stĂ€rker betonen, damit Entwickler wissen, was sie tun mĂŒssen, um die von ihnen benötigte FunktionalitĂ€t zu erreichen.

@ntrp Well Docs-Patches sind mehr als willkommen, und ich werde gerne ĂŒberprĂŒfen, wenn Sie einen einreichen :)

Kann das HinzufĂŒgen einer bestimmten Direktive in angle selbst eine Lösung sein?

Ich stimme der vorherigen Aussage zu, aber es scheint zumindest etwas seltsam, dass a
Rahmen wie eckig hat keinen klaren und sauberen Weg, um zu erreichen
Dies...
Das war wahrscheinlich das Verwirrendste, mit dem ich mich auseinandersetzen musste, als ich es versuchte
Eine Datei hochladen...

Ah ok @caitp , ich habe vor einiger Zeit gelesen, dass Wiki-Pull-Requests nicht wirklich aktiv ausgewertet werden, also habe ich mir nicht die MĂŒhe gemacht, etwas beizutragen. Wenn ich bald etwas Freizeit bekomme, werde ich dann gerne dazu beitragen :) danke.

Mir war nicht klar, dass die ngChange-Direktive auch die Anwesenheit von ngModel erfordert, weshalb hier so viel ĂŒber ngModel diskutiert wird (und deshalb erhalte ich diese Fehlermeldung ). Ich stimme zu, dass eine 2-Wege-Bindung fĂŒr eine Eingabe[type=file] keinen Sinn macht.

Aber was ist der genaue Grund, warum ngModel von ngChange benötigt wird? Meiner Meinung nach ist es absolut sinnvoll, sich an das Änderungsereignis eines Eingabefelds [Typ=Datei] binden zu können, beispielsweise wenn Sie das Formular automatisch senden möchten, sobald eine Datei ausgewĂ€hlt wurde. In einem solchen Fall ist mir der Wert des Felds egal. Mich interessiert nur, dass es sich geĂ€ndert hat. Der beste Weg, den ich gefunden habe, um so etwas zu handhaben, ist die oben von @cztomsik erwĂ€hnte

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

Und das fĂŒhlt sich nicht wirklich nach der besten Lösung an.

ng-change , obwohl sie Ă€hnlich wie die anderen Event-Handler-Direktiven benannt sind, ist eigentlich kein Handler fĂŒr das change Ereignis. Es fĂŒgt einfach ein $viewChangeListener zum ngModelController hinzu, das ausgelöst wird, wenn $setViewValue aufgerufen wird.

Ich stimme zu, es ist ein unglĂŒcklicher Name

Dies ist ein Duplikat von #1236, das mit diesem Kommentar geschlossen wurde: https://github.com/angular/angular.js/issues/1236#issuecomment -29115377

es sei denn, wir sehen einen Vorschlag, wie dies implementiert werden kann, damit es leichtgewichtig und dennoch funktional ist und Framewok-Benutzern keinen ux-Stil aufzwingt, werden wir es in Betracht ziehen. Aber im Moment denken wir, dass Datei-Upload-Probleme komplex genug sind, dass sie als separates Modul gelöst werden mĂŒssen, wahrscheinlich außerhalb des Kerns.

+1

@IgorMinar schau mal hier, etwas dreckig, aber sehr interessantes Beispiel fĂŒr die Umsetzung: https://github.com/danialfarid/angular-file-upload. @danialfarid macht damit große Fortschritte.

ÜberprĂŒfen Sie, wie es fĂŒr alle ein Problem ist, mehrere Probleme mit mehreren Kommentaren geöffnet. Sie mĂŒssen uns ein ngUpload-Modul zur VerfĂŒgung stellen: smile:. Vielleicht können Sie eine HTML5-Implementierung bereitstellen und Anwendungsbeispiele mit https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills#file -api an http://docs.angularjs.org/guide anhĂ€ngen

Wie denkst du zu lösen?

+1

+1

+1

+1

+1

+1

+1

+1

Wow, das ist jetzt etwas peinlich.

+1

Es ist nicht wirklich möglich, 2-Wege-Bindungen fĂŒr Dateieingaben zu haben, insbesondere wenn die Zielbrowser nicht alle die Datei-API unterstĂŒtzen (http://caniuse.com/fileapi) --- Aber selbst wenn dies möglich ist, input[type=file] passt sowieso nicht wirklich hinein. 2-Wege Bindung da ist wirklich unmöglich

Es tut mir leid, aber dies ist eher ein Problem/eine Sicherheitsfunktion der Webplattform als alles andere. Wenn es machbar wÀre, wÀre es getan

@caitp Ich

Etwas so Einfaches wie ein Wrapper dafĂŒr wĂ€re zum Beispiel ein Anfang.

Angesichts der Richtung, in die Angular 2.0 geht (Transpilation von Nur-Winkel-Idiomen, die nicht zu ECMA gehören), denke ich, dass die EinschrÀnkungen der "Webplattform" kein Problem darstellen sollten.

@alle anderen: Was macht Ember in diesem Fall?

Bearbeiten: Entfernen von "erforderlich" aus der Transpiling-Anweisung.

_Nur eine kurze ErlĂ€uterung._ Das Erstellen von Angular 2.0-Apps erfordert keine transpilierte Sprache oder Nicht-ECMA-Idiome. Sie können einfachen ES5-Code verwenden. Wenn Sie die Angular 2.0-Quelle erstellen möchten, mĂŒssen Sie zum Kompilieren Traceur verwenden. NatĂŒrlich können Sie Traceur verwenden, um Ihre eigenen Apps zu erstellen und die gleichen Funktionen zu nutzen, die wir in Angular verwenden, aber das ist völlig optional. Es tut uns leid, wenn es zu diesem Punkt in unseren AnkĂŒndigungen zu Verwirrung gekommen ist.

@EisenbergEffect Mein

Frameworks können die EinschrĂ€nkungen der Webplattform nicht wirklich umgehen. Wir können den Browser nicht zwingen, uns in schreibgeschĂŒtzte IDL-Attribute schreiben zu lassen (was die 2-Wege-Bindung fĂŒr Dateien wirklich unterbricht), und wir können den Browser nicht zwingen, das Dateisystem fĂŒr uns verfĂŒgbar zu machen, was uns wirklich daran hindert irgendwas interessantes damit

@caitp Ich

Vielleicht können wir dieses GesprĂ€ch neu ausrichten auf: "Wie könnte Angular das unterstĂŒtzen?" statt "Es wird nicht in unsere aktuellen Muster passen."

Das Binden an Dateieingaben ist definitiv möglich, ich habe es tatsĂ€chlich bei einem frĂŒheren Projekt fĂŒr AngularJS getan.

Die Tatsache, dass Sie keine bidirektionalen Bindungen mit Dateieingaben durchfĂŒhren können, ist eine Sicherheitsfunktion, und das ist sinnvoll. Autoren werden den Dateipfad nie per Skript festlegen können, aber warum nicht einfach in eine Richtung binden?

Sicher, es bricht das Paradigma, aber wen interessiert es wirklich, wenn es bedeutet, dass Sie eine ng-Änderung und die Möglichkeit erhalten, ĂŒber die Datei-API ohne Hacks auf Dateien zuzugreifen? jQuery kann bei Dateieingaben an ein Änderungsereignis binden. Ist der Angular-Weg so heilig, dass wir ihn nicht einfach innerhalb eines Controllers binden können? Ist es eine technische EinschrĂ€nkung bei der Architektur oder nur eine ideologische Barriere?

Zugegeben, ich war weniger besorgt ĂŒber die 2-Wege-Bindung. Ich wollte die Datei einfach mit dem Rest meines Dokuments veröffentlichen, ohne durch die Rahmen zu springen.

Am 20. Mai 2014 um 7:53 Uhr schrieb Justin Arruda < [email protected] [email protected] >:

@c aitphttps://github.com/caitp Ich

Vielleicht können wir dieses GesprĂ€ch neu ausrichten auf: "Wie könnte Angular das unterstĂŒtzen?" statt "Es wird nicht in unsere aktuellen Muster passen."

—
Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf Gi tHub anhttps://github.com/angular/angular.js/issues/1375#issuecomment -43636326.

Dann haben Sie einen Fall, in dem sich ng-model fĂŒr ein bestimmtes Formularsteuerelement völlig anders verhĂ€lt, und dann haben Leute Fehler wie "Wie kommt es, dass das Formularsteuerelement die falsche Datei sendet, wenn ich den Wert in "foobarblah.txt" Ă€ndere" oder was auch immer. Inkonsistente API -> schlecht.

ngModel ist fĂŒr diese Dinge nicht gerade ideal, weil es bedeutet, dass wir ein bestimmtes Muster haben, in das wir uns einfĂŒgen mĂŒssen, und es fĂŒr Anwendungsautoren sehr schwierig ist, es abzuschalten. DafĂŒr gibt es jedoch Lösungen in angle.dart und dem v2.0.0-Prototyp, so dass dies in Zukunft besser sein wird. Aber wir können wirklich kein weiteres ng-model-Verhalten hinzufĂŒgen, das alles ignoriert, was ng-model derzeit tut, es wĂŒrde keinen Sinn machen

akzeptiert eine Datei und lĂ€dt sie ĂŒber XHR mit Angular . hoch

@guruward wir können dies nicht auf allen unseren

Aber ich bin mir nicht sicher, ob wir das in den Kern einbauen können. Sie mĂŒssen Igor fragen, was er davon hĂ€lt, ein Stoßwellen-Polyfill in den Kern zu liefern.

Ich sage nicht, dass es ein Anwendungsfall ist, den die Leute nie tun wollen, ich kann verstehen, dass dies getan werden soll, ich sage nur, dass es nicht in das ngModel-Muster passt und von uns erfordert, dass wir etwas zusĂ€tzliches Cruft hinzufĂŒgen, um dies zu tun unterstĂŒtzt alle Zielbrowser, so dass das Framework auf diese Weise durchbrochen wird.

Was ist der Schaden bei der Verwendung von Drittanbietermodulen dafĂŒr?

Dieses Polyfill benötigt keinen Flash.

@jreading , das ist kein Polyfill, und es wurde frĂŒher mit einem Flash-Uploader geliefert, es hat es wahrscheinlich immer noch irgendwo.

Es verlĂ€sst sich dabei auf die File API, die nicht in allen Zielbrowsern verfĂŒgbar ist und daher fĂŒr den eckigen 1.x-Kern problematisch ist.

Ohne diese API haben Sie keine Möglichkeit, ohne etwas wie Shockwave an den Datei-Blob zu gelangen.

Es verwendet iframes anstelle von Flash, vielleicht denken Sie daran . Anstatt ĂŒber Semantik zu streiten, wie wĂ€re es mit einer Roadmap? Beginnen wir mit ng-change bei der Dateieingabe fĂŒr Datei-API-fĂ€hige Browser.

@jreading leider hilft dies nicht Browsern, die nicht api-fĂ€hig sind, einschließlich IE9, der immer noch unterstĂŒtzt wird. Wir können keine API liefern, die auf unterstĂŒtztem Browser A, aber nicht unterstĂŒtztem Browser B im Kern funktioniert, ohne dass fĂŒr Leute, die auf IE9-UnterstĂŒtzung angewiesen sind, eine Umgehung erforderlich ist. Und nein, ein iframe macht den Inhalt einer Datei nicht als Blob verfĂŒgbar und macht ihn hochladbar. Hnnggggg.

DafĂŒr gibt es Lösungen in Modulen von Drittanbietern, die Anwendungen nutzen können, wenn sie sich fĂŒr geeignet halten. Dies in Kern A) zu integrieren, macht es diesen Drittanbietermodulen schwieriger und B) unterstĂŒtzt nicht alle Zielbrowser, daher ist dies ein Problem.

Dies ist nur meine Meinung, vielleicht wird Igor oder jemand anderes anderer Meinung sein, aber ich denke nicht, dass es hier der richtige Ansatz ist.

Was ist der Schaden bei der Verwendung von Modulen von Drittanbietern, wenn sie fĂŒr Sie funktionieren und Sie sie benötigen?

Hat nie wirklich impliziert, dass ein Blob fĂŒr den Controller verfĂŒgbar sein muss. Ich gehe aufs Äußerste, aber der grĂ¶ĂŸte Anwendungsfall, den ich sehe, ist die Möglichkeit zu wissen, wann sich die Dateieingabe geĂ€ndert hat, und die Möglichkeit, sie an einen Ruheendpunkt zu senden, der mit dieser iframe-Lösung oder Datei-API und Angular verfĂŒgbar ist hackt.

Module von Drittanbietern sind die einzige Möglichkeit oder aggressive Verbesserungen wie mein Blog-Post (kein Upload fĂŒr Sie!!), aber ich könnte die Frage einfach umdrehen und fragen "Was schadet eine bessere API fĂŒr moderne Browser?"

"Was schadet es, eine bessere API fĂŒr moderne Browser zu haben?"

Dieses Argument ist schwach, weil es die OpportunitĂ€tskosten nicht berĂŒcksichtigt; Es gibt viele andere Dinge, an denen wir (das Kernteam) arbeiten können.

Meinetwegen. FĂŒhlt sich einfach an wie eine riesige LĂŒcke und tief hĂ€ngende FrĂŒchte.

Hier geht es nicht darum, wie dies mit ngModel funktioniert. Ich denke, ngModel könnte die FileList aus dem Eingabefeld auf den Bereich freigeben, aber in die andere Richtung wĂŒrden wir nur das Setzen des Modells auf null/undefiniert zulassen, um unterstĂŒtzt zu werden. Parser/Formatierer wĂŒrden wahrscheinlich nichts tun und Validatoren wĂŒrden nur einfache Dinge tun, wie zum Beispiel das Vorhandensein oder Fehlen von Dateien ĂŒberprĂŒfen.

Das Problem ist (wie bereits erwĂ€hnt), dass dies ohne die Datei-API-UnterstĂŒtzung fĂŒr den Kern nicht möglich ist, da unsere Basislinie IE9 ist und das MehrfachfĂŒllen dieses Zeugs fĂŒr den Kern nicht in Frage kommt.

DarĂŒber hinaus erschwert der Versuch, diese Eingaben auf eine Weise zu handhaben, die nicht browserĂŒbergreifend kompatibel ist, nur fĂŒr Lösungen von Drittanbietern, die nun die Kernlösung bekĂ€mpfen/deaktivieren/umgehen mĂŒssen.

Nicht-Kernlösungen, die damit umgehen, gibt es bereits und sie wurden in dieser Themendiskussion sowie in der vorherigen Ausgabe erwÀhnt

Es gibt viele andere Dinge, die eine grĂ¶ĂŸere Wirkung haben und die wir erreichen möchten. Ich verstehe, dass dies ein relativ hĂ€ufiger Fall ist, aber ich habe immer noch nicht gehört, warum die bestehenden Lösungen nicht ausreichen?

Könnte ein Teil der Energie, die in diese Diskussion gesteckt wird, in die Verbesserung bestehender Lösungen umgeleitet werden, wenn sie es benötigen, oder in eine neue Lösung, die den bestehenden ĂŒberlegen ist?

Ich werde das hier schließen, so wie wir #1236 geschlossen haben. Angular 2 wird entwickelt, um moderne Browser zu unterstĂŒtzen, und damit wird die DateiunterstĂŒtzung leicht verfĂŒgbar sein.

Ich möchte einfach wissen, wann das Änderungsereignis eintritt, damit ich direkt auf das Element zugreifen und die Dateiinformationen abrufen und ĂŒber AJAJ hochladen kann.

@bjoshuanoah wofĂŒr brauchst du dann ngModel? Binden Sie einfach einen Ereignis-Listener an die Eingabe =p

@caitp Ich möchte alles im Controller steuern und nicht mit einer Direktive.

Wenn ich ng-change="uploadFile({$event: $event})" einsetze

Ich kann $scope.uploadFile(event) in meinem Controller haben. und handhabe es dort.

Mein spezifischer Anwendungsfall ist folgender: Datei in s3 hochladen, URL auf mein Modell anwenden.

stattdessen muss ich in den Bereich einbrechen, um dasselbe zu tun. Sehr nervig:

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

Ich wĂŒnschte, jemand wĂŒrde dieses Thema töten. damit wir alle weitermachen können :)

Am 25. Juli 2014 um 9:22 Uhr schrieb Brian < [email protected] [email protected] >:

Ich möchte einfach wissen, wann das Änderungsereignis eintritt, damit ich direkt auf das Element zugreifen und die Dateiinformationen abrufen und ĂŒber AJAJ hochladen kann.

—
Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf Gi tHub an

+1

+1

+1000000000000000

+1

+1

+1

+1

+100500

+1
Ich bin mir nicht sicher, warum Ajax ein Problem ist. Möglicherweise möchten Sie Daten aus einer CSV-Datei auf dem lokalen Computer in ein Angular-Modell laden. Wenn ng-change bei der Dateieingabe in Angular funktionieren wĂŒrde, wĂ€re dies einfach, derzeit ist dies nicht der Fall. Dieses Szenario erfordert ĂŒberhaupt kein Ajax oder eine Server-API. Ich bin mir auch nicht sicher, warum das geschlossen ist?

Meine aktuelle Problemumgehung ist, Folgendes zu tun

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

und in meinem Controller habe ich einfach so etwas wie

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

Es stinkt zwar ziemlich, ich habe das GefĂŒhl, dass ich eckig als Werkzeug bastardiere. Jeder Einblick, wie man dies auf eine eckigere Weise tun kann, wĂ€re sehr dankbar.

:Herz Herz:

Hier ist ein Segelboot: :Segelboot:

@samccone Ist scope() nicht verfĂŒgbar, wenn der Debug-Modus ausgeschaltet ist?

@geetsce Das ist richtig (in 1.3.x und höher)

Welp, in 1.2 Land ist alles gut.

@Narretz hast du eine bessere Lösung?

Das funktioniert fĂŒr mich, es ist inspiriert von 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

Es wird nicht passieren... Lass es los, lass es gehen...

+1

Wie @samccone sagte,

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

Dies ist nicht die Vorgehensweise von Angular. Es ist seltsam.

+1

+1

+1

hey @caitp @Narretz Wenn ihr

Nochmals vielen Dank fĂŒr alles, was Sie tun :palm_tree:

+1

+1

+1

+1

+1

ng-Datei-Upload funktioniert super.

+1 fĂŒr @neokyol!! Es funktioniert super!

diese gemeinsame Funktion muss standardmĂ€ĂŸig im Framework vorhanden sein

hilfreich

+1

+1

+1

+1

+1

das hat bei mir funktioniert, kann helfen

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 können Sie bitte ein Plunker-Beispiel angeben.

+1

+1

+1 DafĂŒr sollte eine Direktive in die Kernbibliothek eingebaut sein. Es ist ziemlich lĂ€cherlich

+1

+1
ist das Feature fĂŒr eine der nĂ€chsten Versionen geplant?

+1

+1

Wie geht das in Projekten, in denen $scope nie in den Controller injiziert wird. Ich verwende Laravel Angular, das die GULP- und ES6-Methode verwendet, um Controller zu deklarieren.

dh

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: {}
}

Ich habe eine Arbeit gefunden, die ich glaube. http://stackoverflow.com/questions/38449126/how-to-setup-ng-file-upload-in-laravel-angular-project/38486379#38486379

+1

@ntrp @guruward @coli @lgersman @jgoldber @Siyfion
Wie haben Sie die Validierung behoben fĂŒr
Meine BestÀtigung:
this.catalougeForm = this.catalougeFormBuilder.group({
catalougeIconName: ['',Validators.required]
});
HTML:
(change)="changeListener($event)">

Mein Validator betrachtet den Wert von catalougeIconName als leer/null, nachdem ich hochgeladen habe.
Bild wird gesendet, aber Validator funktioniert nicht

Irgendwelche Updates dazu?

Irgendwelche Aktualisierungen?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen