2013-05-16 14 views
11

Ich versuche, Winkel zu erhalten, um den Inhalt einer Datei zu lesen, die der Benutzer über eine <input type="file" Steuerung auswählt. Obwohl Winkel Richtlinien für Datei-Upload-Kontrollen nicht hat, sollte es leicht sein, dass zu beheben mit einem Aufruf an $apply:HTML5 Datei-Upload mit AngularJS

function MyController($scope) { 
    $('#myFile').on('change', function() { 
    var that = this; 
    $scope.$apply(function() { $scope.files = that.files }); 
    }); 
} 

Leider wird das Ereignis nie ausgelöst. Es ist, als ob der Selektor nicht auf das richtige DOM-Element verweisen kann: Obwohl der Selektor das Element findet, ist die Liste der Dateien immer leer. Das passiert auch, wenn ich mit der js-Konsole herumstochere. Der DOM-Inspektor hat stattdessen die Dateiliste unter seinen Eigenschaften.

Es macht mich verrückt, aber die einzige Möglichkeit, die ich bisher habe, ist die Verwendung eines Inline-Event-Handlers, der eine globale Variable zuweist. Warum gibt der jquery-Selektor ein anderes Element zurück? Gibt es einen Vorlagen-Kompilierungs-Hokuspokus, der eckig macht, was Selektoren verwirrt? Hier

Antwort

14

ist, was ich tue:

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

app.directive('filelistBind', function() { 
    return function(scope, elm, attrs) { 
    elm.bind('change', function(evt) { 
     scope.$apply(function() { 
     scope[ attrs.name ] = evt.target.files; 
     console.log(scope[ attrs.name ]); 
     }); 
    }); 
    }; 
}); 

Vorlage:

<input type="file" filelist-bind name="files"/> 
<p>selected files : <pre>{{ files | json }}</pre></p> 

Diese Art der Aufgabe, Sie auf jeden Fall Gebrauch der Richtlinie machen wollen. Aber ich denke, dass Ihr Hauptanliegen ist, wie Sie auf die ausgewählte Datei Objekte zugreifen und mein Beispiel sollte dies verdeutlichen.

+0

nett. Ich habe am Ende eine globale Funktion im Controller definiert und sie aus dem Inline Event Handler aufgerufen. Da $ scope im äußeren closure liegt, kann ich die Änderungen zumindest anwenden. Die Richtlinie ist definitiv eine eher "eckige" Art, dies zu tun. Aber die Frage lautet: Warum gibt der Selektor ein 'input'-Element zurück, das genau so aussieht wie das, mit dem der Benutzer interagiert, aber es ist tatsächlich nicht? – BruceBerry

+0

mmmh das funktioniert nicht für mich. Wenn ich deinen Plunkr laufe, bekomme ich immer Dateien: { "0": {} } mache ich etwas falsch? – pomarc

+0

@pomarc IIRC, es hat funktioniert ... Aber es scheint, dass moderne Browser nicht unterstützen, Dateiobjekt zu stringieren. Sie müssen direkt auf Eigenschaften zugreifen, um sie in Ihrer Ansicht anzuzeigen. – Tosh

2

Wenn Sie für Datei-Upload mit Winkeln suchen, können Sie dieses Plugin verwenden

https://github.com/danialfarid/angular-file-upload

Es ist im Grunde eine Richtlinie wie die Antwort von Tosh, die mit FileAPI Flash polyfill Pflege von nicht-HTML5-Browser nimmt und $ http.uploadFile Funktion zum Hochladen der eigentlichen Datei über AJAX.

1

Dieser site verwendet den Angular-Dienst für das Hochladen von HTML5-Dateien. Eine einfache Möglichkeit besteht darin, einen Controller einzurichten, der den Dienst aufruft und die Benutzeroberfläche aktualisiert, wenn der asynchrone Aufruf abgeschlossen ist.

Controller:

myapp.controller('fileUploadCtrl', ['$scope', '$q', 'FileInputService', function ($scope, $q, FileInputService) { 
      $scope.fileInputContent = ""; 
      $scope.onFileUpload = function (element) { 
       $scope.$apply(function (scope) { 
        var file = element.files[0]; 
        FileInputService.readFileAsync(file).then(function (fileInputContent) { 
         $scope.fileInputContent = fileInputContent; 
        }); 
       }); 
      }; 
     }]); 

Service:

myapp.service('FileInputService', function ($q) { 

    this.readFileAsync = function (file) { 
     var deferred = $q.defer(), 
     fileReader = new FileReader(), 
     fileReader.readAsText(file); 

     fileReader.onload = function (e) { 
      deferred.resolve(e.target.result); 
     }; 
     return deferred.promise; 
    }; 
}); 

Vorlage:

Choose File <input type="file" onchange="angular.element(this).scope().onFileUpload(this)"> 
<br /> 
{{fileInputContent}} 

Referenz: Sie können den vollständigen Quellcode finden und Referenz on this site.

Verwandte Themen