it-swarm.com.de

Dateiauswahl mit Angular JS

Ich möchte eine Datei mit AngularJS abholen:

HTML:

<div ng-controller="TopMenuCtrl">
    <button class="btn" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button>
    <input type="file" ng-model="filepick" ng-change="pickimg()" multiple />
    <output id="list"></output> 
</div>

javascript:

angular.module('plunker', ['ui.bootstrap']);
function TopMenuCtrl($scope) {
    $scope.pickimg = function() {
        alert('a');
    };
}

Wie kann ich die Eingabedatei onchange an die AngularJS pickimg-Funktion binden? Wie kann ich die hochgeladenen Dateien bearbeiten?

26
mcbjam

Angular unterstützt ng-change for input [type = file] noch nicht. Daher müssen Sie die onchange-Implementierung selbst ausführen. 

Definieren Sie in HTML zunächst Javascript für onchange wie folgt:

<input ng-model="photo"
       onchange="angular.element(this).scope().file_changed(this)"
       type="file" accept="image/*" />

Definieren Sie dann in Ihrem Angular-Controller-Code die Funktion:

$scope.file_changed = function(element) {

     $scope.$apply(function(scope) {
         var photofile = element.files[0];
         var reader = new FileReader();
         reader.onload = function(e) {
            // handle onload
         };
         reader.readAsDataURL(photofile);
     });
};
49
Teemu Kurppa

Ich habe die obige Methode verwendet, um zu versuchen, ein Vorschaubild zu laden, wenn eine neue Datei ausgewählt wird. Es funktionierte jedoch nicht, als ich es so ausprobierte:

$scope.file_changed = function(element, $scope) {

     $scope.$apply(function(scope) {
         var photofile = element.files[0];
         var reader = new FileReader();
         reader.onload = function(e) {
            $scope.prev_img = e.target.result;
         };
         reader.readAsDataURL(photofile);
     });
});

Ich grub mehr hinein und stellte fest, dass $ scope. $ Apply in der Datei "reader.onLoad" sein sollte. Andernfalls funktionieren Änderungen an $ scope-Variablen nicht. Daher habe ich Folgendes getan und es hat funktioniert:

$scope.file_changed = function(element) {

        var photofile = element.files[0];
        var reader = new FileReader();
        reader.onload = function(e) {
            $scope.$apply(function() {
                $scope.prev_img = e.target.result;
            });
        };
        reader.readAsDataURL(photofile);
 };
17
Sharon Abu

Teemu-Lösung funktioniert nicht für IE9.

Ich habe eine einfache eckige Direktive mit Flash polyfill für Browser zusammengestellt, die kein HTML5 FormData unterstützen. Sie können auch das Fortschrittsereignis hochladen. 

https://github.com/danialfarid/ng-file-upload Demo: http://angular-file-upload.appspot.com/

<script src="angular.min.js"></script>
<script src="ng-file-upload.js"></script>

<div ng-controller="MyCtrl">
  <input type="text" ng-model="additionalData">
  <div ngf-select ng-model="files" >
</div>

regler:

Upload.upload({
    url: 'my/upload/url',
    data: additionalData,
    file: files
  }).then(success, error, progress); 
6
danial

Nachfolgend ist mein Ansatz mit einer Richtlinie.

Richtlinie

angular
  .module('yourModule')
  .directive('fileChange', function() {
    return {
     restrict: 'A',
     scope: {
       handler: '&'
     },
     link: function (scope, element) {
      element.on('change', function (event) {
        scope.$apply(function(){
          scope.handler({files: event.target.files});
        });
      });
     }
    };
});

HTML

<input type="file" file-change handler="fileSelect(files)">

Regler

fileSelect = function (files) {
      var file = files[0];
      //you will get the file object here
}
3
Madura Pradeep

Hier ist eine einfache Direktive, die ich geschrieben habe, um dieses Problem zu lösen, die die eckige Art des Anfügens von Ereignissen widerspiegelt. 

Sie können die Direktive folgendermaßen verwenden:

HTML

<input type="file" file-change="yourHandler($event, files)" />

Wie Sie sehen, können Sie die ausgewählten Dateien in Ihren Event-Handler einfügen, wie Sie ein $ -Ereignis-Objekt in einen beliebigen ng-Event-Handler einfügen würden.

Javascript

angular
  .module('yourModule')
  .directive('fileChange', ['$parse', function($parse) {

    return {
      require: 'ngModel',
      restrict: 'A',
      link: function ($scope, element, attrs, ngModel) {

        // Get the function provided in the file-change attribute.
        // Note the attribute has become an angular expression,
        // which is what we are parsing. The provided handler is 
        // wrapped up in an outer function (attrHandler) - we'll 
        // call the provided event handler inside the handler()
        // function below.
        var attrHandler = $parse(attrs['fileChange']);

        // This is a wrapper handler which will be attached to the
        // HTML change event.
        var handler = function (e) {

          $scope.$apply(function () {

            // Execute the provided handler in the directive's scope.
            // The files variable will be available for consumption
            // by the event handler.
            attrHandler($scope, { $event: e, files: e.target.files });
          });
        };

        // Attach the handler to the HTML change event 
        element[0].addEventListener('change', handler, false);
      }
    };
  }]);
2
Simon Robb

Mit Maduras Antwort von oben, hier der vollständige Ablauf zum Lesen einer lokalen JSON-Datei:

Direktive erstellen:

angular
  .module('app.services')
  .directive('fileChange', function() {
    return {
     restrict: 'A',
     scope: {
       handler: '&'
     },
     link: function (scope, element) {
      element.on('change', function (event) {
        scope.$apply(function(){
          scope.handler({files: event.target.files});
        });
      });
     }
    };
});

HTML:

<input type="file" file-change handler="fileSelect(files)">

Javascript:

$scope.fileSelect = function(files) {
  var file = files[0];
  var reader = new FileReader();
  reader.onload = function(e) {
    console.log("on load", e.target.result);
  }
  reader.readAsText(file);
}
2
Snowman

Ich habe eine Anweisung gemacht. Hier ist die Geige .
Die Anwendung funktioniert zum Auswählen von csvs und zum Anzeigen dieser als HTML-Tabellen.
Mit der Direktive on-file change können Sie in den Controllern selbst die Logik für das Lesen und Parsen von Dateien (mit Services) definieren, die mehr Flexibilität bietet. Die ac.onFileChange-Funktion, die an das on-file-change-Attribut übergeben wird, wird zum Handler für das Eingabeänderungsereignis in der Direktive.

(function (angular, document) {

   angular
      .module("app.directives", [])
      .directive("onFileChange", ["$parse", function ($parse) {
         return {
            restrict: "A",
            link: function (scope, ele, attrs) {
               // onFileChange is a reference to the same function which you would define 
               // in the controller. So that you can keep your logic in the controller.
               var onFileChange = $parse(attrs.onFileChange.split(/\(/)[0])(scope)
               ele.on("change", onFileChange)
               ele.removeAttr("on-file-change")
            }
         }
      }])

   angular
      .module("app.services", [])
      .service("Parse", ["$q", function ($q) {
         var Parse = this
         Parse.csvAsGrid = function (file) {
            return $q(function (resolve, reject) {
               try {
                  Papa.parse(file, {
                     complete: function (results) {
                        resolve(results.data)
                     }
                  })
               } catch (e) {
                  reject(e)
               }
            })
         }
      }])

   angular
      .module("app", ["app.directives", "app.services"])
      .controller("appCtrl", ["$scope", "Parse", function ($scope, Parse) {
         var ac = this
         ac.fileName = ""
         ac.onFileChange = function (event) {
            if (!event.target.files.length) {
               return
            }
            Parse.csvAsGrid(event.target.files[0]).then(outputAsTable)
         }

         ac.clearInput = function (event) {
            var input = angular.element(event.target)
            input.val("")
            document.getElementById("output").innerHTML = ""
         }

         function outputAsTable(grid) {
            var table = ['<table border="1">']
            grid.map(function (row) {
               table.Push('<tr>')
               row.map(function (cell) {
                  table.Push('<td>' + cell.replace(/["']/g, "") + '</td>')
               })
               table.Push('</tr>')
            })
            table.Push('</table>')
            document.getElementById("output").innerHTML = table.join("\n")
         }
      }])

})(angular, document)
table {
  border-collapse: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.2/papaparse.min.js"></script>

<div ng-app="app" ng-controller="appCtrl as ac">
  <label>Select a comma delimited CSV file:-</label>  
  <input id="filePicker" type="file" on-file-change="ac.onFileChange(event)" ng-click="ac.clearInput($event)"/>{{ac.fileName}}  
</div>
<div id="output"></div>

0
Vikas Gautam

Richtlinie, die den ng-model-Controller verwendet:

app.directive("selectNgFiles", function() {
  return {
    require: "ngModel",
    link: function postLink(scope,elem,attrs,ngModel) {
      elem.on("change", function(e) {
        var files = elem[0].files;
        ngModel.$setViewValue(files);
      })
    }
  }
});

Verwendungszweck:

<input type="file" select-ng-files ng-model="fileArray"
       ng-change="pickimg()" multiple>

Weitere Informationen finden Sie unter Arbeitsdemo der Richtlinie, die mit ng-model funktioniert .

0
georgeawg