287

私は角度が初めてです。このフィールドで「変更」が発生するたびに、HTML の「ファイル」フィールドからアップロードされたファイル パスを読み取ろうとしています。「onChange」を使用すると機能しますが、「ng-change」を使用して角度を付けて使用すると機能しません。

<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()が呼び出されることはありません。Firebug もエラーを表示しません。

4

15 に答える 15

27

クリーンな方法は、「変更」イベントにバインドする独自のディレクティブを作成することです。IE9 は FormData をサポートしていないため、change イベントから実際にファイル オブジェクトを取得することはできません。

FileAPI ポリフィルで IE を既にサポートしているng-file-uploadライブラリを使用して、サーバーへのファイルの投稿を簡素化できます。これを実現するためにディレクティブを使用します。

<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);
      }); 
    }
  }
}];
于 2013-08-24T17:01:08.187 に答える
26

@Stuart Axon のアイデアを拡張して、ファイル入力に双方向バインディングを追加しました (つまり、モデル値を 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("");
                }
            });
        }
    };
}]);

デモ

于 2015-01-08T06:33:26.873 に答える
20

ここでの他のいくつかの良い答えと同様に、この問題を解決するためのディレクティブを書きましたが、この実装は、イベントを添付する角度のある方法をより厳密に反映しています。

次のようにディレクティブを使用できます。

HTML

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

ご覧のとおり、$event オブジェクトを ng イベント ハンドラーに挿入するように、選択したファイルをイベント ハンドラーに挿入できます。

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);
      }
    };
  }]);
于 2014-10-27T15:28:56.710 に答える
4

最も単純な Angular jqLit​​e バージョン。

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()">
于 2015-01-05T23:44:38.710 に答える
1

以下に基づく完全すぎるソリューション:

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

入力フィールドを非表示にして画像に置き換える簡単な方法。ここではソリューションの後、角度のハックも必要ですが、仕事をします[TriggerEventは期待どおりに機能しません]

ソリューション:

  • 入力フィールドを display:none に配置します [入力フィールドは DOM に存在しますが、表示されません]
  • 画像の直後に画像を配置します画像上で nb-click() を使用してメソッドをアクティブにします

画像がクリックされると、入力フィールドで DOM アクション「クリック」をシミュレートします。ほら!

 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!!!
    };
于 2015-12-13T20:29:47.903 に答える
1

ファイル入力の変更をリッスンするもう 1 つの興味深い方法は、入力ファイルの ng-model 属性を監視することです。もちろん、FileModel はカスタム ディレクティブです。

このような:

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

JS コード ->

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

それが誰かを助けることを願っています。

于 2017-04-17T18:45:02.350 に答える
0

Angular 要素 (ディレクティブのルート要素など) は jQuery [Lite] オブジェクトです。これは、次のようにイベント リスナーを登録できることを意味します。

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

これが jQuery イベント委任です。ここでは、リスナーがディレクティブのルート要素にアタッチされています。イベントがトリガーされると、登録された要素にバブルアップし、jQuery は、定義されたセレクターに一致する内部要素でイベントが発生したかどうかを判断します。その場合、ハンドラーが起動します。

この方法の利点は次のとおりです。

  • ハンドラーは、ディレクティブ スコープが破棄されたときに自動的にクリーンアップされる $element にバインドされます。
  • テンプレートにコードがない
  • イベントハンドラーを登録するときにターゲットデリゲート(入力)がまだレンダリングされていない場合でも機能します(ng-ifまたはを使用する場合などng-switch

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

于 2017-09-08T00:34:20.300 に答える