web-dev-qa-db-de.com

AngularJs: Wie prüfe ich auf Änderungen in den Dateieingabefeldern?

Ich bin neu im Winkel. Ich versuche, den hochgeladenen Dateipfad aus dem HTML-Dateifeld zu lesen, wenn in diesem Feld eine Änderung erfolgt. Wenn ich 'onChange' verwende, funktioniert es, aber wenn ich es mit 'ng-change' verwinkelt, funktioniert es nicht.

<script>
   var DemoModule = angular.module("Demo",[]);
   DemoModule .controller("form-cntlr",function($scope){
   $scope.selectFile = function()
   {
        $("#file").click();
   }
   $scope.fileNameChaged = function()
   {
        alert("select file");
   }
});
</script>

<div ng-controller="form-cntlr">
    <form>
         <button ng-click="selectFile()">Upload Your File</button>
         <input type="file" style="display:none" 
                          id="file" name='file' ng-Change="fileNameChaged()"/>
    </form>  
</div>

fileNameChaged () ruft niemals auf. Firebug zeigt auch keine Fehler an.

265
manish

Keine verbindliche Unterstützung für die Dateiuploadsteuerung

https://github.com/angular/angular.js/issues/1375

<div ng-controller="form-cntlr">
        <form>
             <button ng-click="selectFile()">Upload Your File</button>
             <input type="file" style="display:none" 
                id="file" name='file' onchange="angular.element(this).scope().fileNameChanged(this)" />
        </form>  
    </div>

anstatt 

 <input type="file" style="display:none" 
    id="file" name='file' ng-Change="fileNameChanged()" />

kannst du es versuchen

<input type="file" style="display:none" 
    id="file" name='file' onchange="angular.element(this).scope().fileNameChanged()" />

Hinweis: Dies erfordert, dass sich die Winkelanwendung immer im Debug-Modus befindet. Dies funktioniert nicht im Produktionscode, wenn der Debug-Modus deaktiviert ist.

und in Ihrer Funktion ändert sich .__ statt

$scope.fileNameChanged = function() {
   alert("select file");
}

kannst du es versuchen

$scope.fileNameChanged = function() {
  console.log("select file");
}

Nachfolgend finden Sie ein Arbeitsbeispiel für das Hochladen von Dateien mit Drag-Drop-Upload http://jsfiddle.net/danielzen/utp7j/

Angular File Upload-Informationen

URL für das Hochladen von AngularJS-Dateien in ASP.Net

http://cgeers.com/2013/05/03/angularjs-file-upload/

AngularJs nativer Multi-File-Upload mit Fortschritt mit NodeJS

http://jasonturim.wordpress.com/2013/09/12/angularjs-native-multi-file-upload-with-progress/

ngUpload - Ein AngularJS-Dienst zum Hochladen von Dateien mithilfe von iframe 

http://ngmodules.org/modules/ngUpload

229
JQuery Guru

Ich habe eine kleine Anweisung gemacht, um auf Änderungen der Dateieingabe zu achten.

JSFiddle anzeigen

view.html:

<input type="file" custom-on-change="uploadFile">

controller.js:

app.controller('myCtrl', function($scope){
    $scope.uploadFile = function(event){
        var files = event.target.files;
    };
});     

director.js:

app.directive('customOnChange', function() {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      var onChangeHandler = scope.$eval(attrs.customOnChange);
      element.on('change', onChangeHandler);
      element.on('$destroy', function() {
        element.off();
      });

    }
  };
});
454
sqren

Dies ist eine Verfeinerung einiger anderer, und die Daten landen in einem ng-Modell, das normalerweise gewünscht ist.

Markup (einfach eine Attributdatei erstellen, damit die Direktive sie finden kann)

<input
    data-file
    id="id_image" name="image"
    ng-model="my_image_model" type="file">

JS

app.directive('file', function() {
    return {
        require:"ngModel",
        restrict: 'A',
        link: function($scope, el, attrs, ngModel){
            el.bind('change', function(event){
                var files = event.target.files;
                var file = files[0];

                ngModel.$setViewValue(file);
                $scope.$apply();
            });
        }
    };
});
37
Stuart Axon

Die saubere Methode ist, eine eigene Direktive zu schreiben, die an das Änderungsereignis gebunden ist. Um Sie wissen zu lassen, dass IE9 FormData nicht unterstützt, können Sie das Dateiobjekt nicht wirklich vom Änderungsereignis abrufen.

Sie können ng-file-upload library verwenden, die bereits IE mit FileAPI polyfill unterstützt, und die Veröffentlichung der Datei auf dem Server vereinfachen. Es verwendet eine Direktive, um dies zu erreichen. 

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

<div ng-controller="MyCtrl">
  <input type="file" ngf-select="onFileSelect($files)" multiple>
</div>

JS:

//inject angular file upload directive.
angular.module('myApp', ['ngFileUpload']);

var MyCtrl = [ '$scope', 'Upload', function($scope, Upload) {
  $scope.onFileSelect = function($files) {
    //$files: an array of files selected, each file has name, size, and type.
    for (var i = 0; i < $files.length; i++) {
      var $file = $files[i];
      Upload.upload({
        url: 'my/upload/url',
        data: {file: $file}
      }).then(function(data, status, headers, config) {
        // file is uploaded successfully
        console.log(data);
      }); 
    }
  }
}];
27
danial

Ich habe die Idee von @Stuart Axon erweitert, um die bidirektionale Bindung für die Dateieingabe hinzuzufügen (d. H. Das Zurücksetzen der Eingabe durch Rücksetzen des Modellwerts auf null):

app.directive('bindFile', [function () {
    return {
        require: "ngModel",
        restrict: 'A',
        link: function ($scope, el, attrs, ngModel) {
            el.bind('change', function (event) {
                ngModel.$setViewValue(event.target.files[0]);
                $scope.$apply();
            });

            $scope.$watch(function () {
                return ngModel.$viewValue;
            }, function (value) {
                if (!value) {
                    el.val("");
                }
            });
        }
    };
}]);

Demo

26
JLRishe

Ähnlich wie bei einigen anderen guten Antworten habe ich auch eine Direktive geschrieben, um dieses Problem zu lösen. Diese Implementierung spiegelt jedoch eher die winklige Art des Anfügens von Ereignissen wider. 

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

Diese Direktive übergibt auch die ausgewählten Dateien:

/**
 *File Input - custom call when the file has changed
 */
.directive('onFileChange', function() {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      var onChangeHandler = scope.$eval(attrs.onFileChange);

      element.bind('change', function() {
        scope.$apply(function() {
          var files = element[0].files;
          if (files) {
            onChangeHandler(files);
          }
        });
      });

    }
  };
});

Das HTML, wie man es benutzt:

<input type="file" ng-model="file" on-file-change="onFilesSelected">

In meinem Controller:

$scope.onFilesSelected = function(files) {
     console.log("files - " + files);
};
16
ingaham

Ich empfehle, eine Direktive zu erstellen

<input type="file" custom-on-change handler="functionToBeCalled(params)">

app.directive('customOnChange', [function() {
        'use strict';

        return {
            restrict: "A",

            scope: {
                handler: '&'
            },
            link: function(scope, element){

                element.change(function(event){
                    scope.$apply(function(){
                        var params = {event: event, el: element};
                        scope.handler({params: params});
                    });
                });
            }

        };
    }]);

diese Direktive kann mehrmals verwendet werden, sie verwendet ihren eigenen Bereich und ist nicht vom übergeordneten Bereich abhängig. Sie können der Handler-Funktion auch einige Parameter zuweisen. Die Handler-Funktion wird mit einem Bereichsobjekt aufgerufen, das beim Ändern der Eingabe aktiv war. $ apply aktualisiert Ihr Modell bei jedem Aufruf des Änderungsereignisses 

6
Julia Usanova

Die einfachste Angular-Version von JqLite.

JS:

.directive('cOnChange', function() {
    'use strict';

    return {
        restrict: "A",
        scope : {
            cOnChange: '&'
        },
        link: function (scope, element) {
            element.on('change', function () {
                scope.cOnChange();
        });
        }
    };
});

HTML:

<input type="file" data-c-on-change="your.functionName()">
4
Jonáš Krutil

Arbeitsdemo der "files-input" Direktive, die mit ng-change funktioniert1

Damit ein <input type=file>-Element mit der ng-change - Direktive funktioniert, ist eine benutzerdefinierte Direktive erforderlich, die mit der ng-model - Direktive funktioniert.

<input type="file" files-input ng-model="fileList" 
       ng-change="onInputChange()" multiple />

Die DEMO

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

.controller("ctrl", function($scope) {
     $scope.onInputChange = function() {
         console.log("input change");
     };
})
<script src="//unpkg.com/angular/angular.js"></script>
  <body ng-app="app" ng-controller="ctrl">
    <h1>AngularJS Input `type=file` Demo</h1>
    
    <input type="file" files-input ng-model="fileList" 
           ng-change="onInputChange()" multiple />
    
    <h2>Files</h2>
    <div ng-repeat="file in fileList">
      {{file.name}}
    </div>
  </body>

1
georgeawg

Winkelelemente (z. B. das Stammelement einer Direktive) sind jQuery [Lite] -Objekte. Dies bedeutet, dass wir den Ereignis-Listener wie folgt registrieren können:

link($scope, $el) {
    const fileInputSelector = '.my-file-input'

    function setFile() {
        // access file via $el.find(fileInputSelector).get(0).files[0]
    }

    $el.on('change', fileInputSelector, setFile)
}

Dies ist die Delegierung von jQuery-Ereignissen. Hier wird der Listener an das Stammelement der Direktive angehängt. Wenn das Ereignis ausgelöst wird, sprudelt es zum registrierten Element und jQuery bestimmt, ob das Ereignis von einem inneren Element stammt, das mit dem definierten Selektor übereinstimmt. Wenn dies der Fall ist, wird der Handler ausgelöst.

Vorteile dieser Methode sind:

  • der Handler ist an das Element $ gebunden, das automatisch gelöscht wird, wenn der Richtlinienbereich gelöscht wird.
  • kein Code in der Vorlage
  • funktioniert auch, wenn der Zieldelegat (Eingabe) noch nicht gerendert wurde, wenn Sie den Ereignishandler registrieren (z. B. bei Verwendung von ng-if oder ng-switch).

http://api.jquery.com/on/

0
Matt S

Ich habe es so gemacht;

<!-- HTML -->
<button id="uploadFileButton" class="btn btn-info" ng-click="vm.upload()">    
<span  class="fa fa-Paperclip"></span></button>
<input type="file" id="txtUploadFile" name="fileInput" style="display: none;" />
// self is the instance of $scope or this
self.upload = function () {
   var ctrl = angular.element("#txtUploadFile");
   ctrl.on('change', fileNameChanged);
   ctrl.click();
}

function fileNameChanged(e) {
    console.log(self.currentItem);
    alert("select file");
}
0
Ali Sakhi

Sie können einfach den untenstehenden Code in onchange hinzufügen, und die Änderung wird erkannt. Sie können eine Funktion auf X-Klick oder etwas zum Entfernen von Dateidaten schreiben.

document.getElementById(id).value = "";
0
Jijo Thomas

Zu vollständige Lösung basierend auf:

`onchange="angular.element(this).scope().UpLoadFile(this.files)"`

Eine einfache Möglichkeit, das Eingabefeld auszublenden und durch ein Bild zu ersetzen, hier nach einer Lösung, die auch einen Winkel auf Winkel erfordert, aber die Aufgabe erfüllt. [TriggerEvent funktioniert nicht wie erwartet]

Die Lösung:

  • das Eingabefeld in die Anzeige setzen: none [das Eingabefeld ist im DOM vorhanden, aber nicht sichtbar]
  • platzieren Sie Ihr Bild direkt nach Verwenden Sie Nb-click (), um eine Methode zu aktivieren

Wenn das Bild angeklickt wird, "simulieren" Sie eine DOM-Aktion in das Eingabefeld. Et voilà!

 var tmpl = '<input type="file" id="{{name}}-filein"' + 
             'onchange="angular.element(this).scope().UpLoadFile(this.files)"' +
             ' multiple accept="{{mime}}/*" style="display:none" placeholder="{{placeholder}}">'+
             ' <img id="{{name}}-img" src="{{icon}}" ng-click="clicked()">' +
             '';
   // Image was clicked let's simulate an input (file) click
   scope.inputElem = elem.find('input'); // find input in directive
   scope.clicked = function () {
         console.log ('Image clicked');
         scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!!
    };
0
Fulup

Eine weitere interessante Möglichkeit, Änderungen an den Dateieingaben zu überwachen, besteht in der Überwachung des Attributs ng-model der Eingabedatei. Natürlich ist FileModel eine benutzerdefinierte Direktive.

So was:

HTML -> <input type="file" file-model="change.fnEvidence">

JS-Code ->

$scope.$watch('change.fnEvidence', function() {
                    alert("has changed");
                });

Hoffe es kann jemandem helfen.

0
halbano