2013-05-16 3 views
11

Sto cercando di ottenere angolare per leggere il contenuto di un file che l'utente seleziona tramite un controllo <input type="file". Anche se angolare non ha direttive per i controlli di upload di file, dovrebbe essere facile da risolvere che con una chiamata a $apply:Caricamento file HTML5 con AngularJS

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

Purtroppo, l'evento viene mai sparato. È come se il selettore non fosse in grado di riferirsi all'elemento DOM corretto: anche se il selettore trova l'elemento, l'elenco dei file è sempre vuoto. Questo succede anche se mi aggiro con la console js. L'ispettore DOM ha invece l'elenco dei file tra le sue proprietà.

Mi fa impazzire, ma l'unico modo per farlo funzionare finora è utilizzare un gestore di eventi inline che assegna a una variabile globale. Perché il selettore jquery restituisce un altro elemento? C'è qualche modello di compilation mumbo-jumbo che fa l'angolare che confonde i selettori?

risposta

14

Ecco quello che faccio:

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

modello:

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

Questo tipo di attività, è sicuramente voglia di fare uso di direttiva. Ma penso che la vostra preoccupazione principale sia come accedere al file selezionato oggetti e il mio esempio dovrebbe chiarirlo.

+0

bello. Ho finito per definire una funzione globale nel controller e chiamarla dal gestore eventi in linea. Poiché $ scope è nella chiusura esterna, almeno posso $ applicare le modifiche. La direttiva è sicuramente un modo più "angolare" per farlo. Ma la domanda è la seguente: perché il selettore restituisce un elemento 'input' che assomiglia esattamente a quello con cui l'utente sta interagendo, ma in realtà non lo è? – BruceBerry

+0

mmmh questo non funziona per me. se eseguo il tuo plunkr, ottengo sempre file : { "0": {} } faccio qualcosa di sbagliato? – pomarc

+0

@pomarc IIRC, funzionava ... Ma sembra che i browser moderni non supportino l'oggetto file di stringing. Devi accedere direttamente alle proprietà per mostrarle nella tua vista. – Tosh

2

Se siete alla ricerca di upload di file con angolare è possibile utilizzare questo plugin

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

Si tratta essenzialmente di una direttiva come la risposta di Tosh che si prende cura dei browser non HTML5 con FileAPI Flash polyfill e ha $ funzione http.uploadFile per caricare il file reale tramite AJAX.

1

Questo site utilizza il servizio angolare per il caricamento di file HTML5. Un modo semplice è configurare un controller che chiama il servizio e aggiorna l'interfaccia utente quando la chiamata asincrona è completata.

regolatore:

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

servizio:

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

modello:

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

Riferimento: È possibile trovare il codice sorgente completo e riferimento on this site.