it-swarm.asia

AngularJs: كيفية التحقق من التغييرات في حقول إدخال الملفات؟

أنا جديد على الزاوي. أحاول قراءة مسار الملف الذي تم تحميله من حقل "ملف" 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 أيضا لا تظهر أي خطأ.

268
manish

لا يوجد دعم ملزم للتحكم في تحميل الملف

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>

بدلا من

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

هل تجرب

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

ملاحظة: هذا يتطلب أن يكون التطبيق الزاوي دائمًا في وضع التصحيح . لن يعمل هذا في رمز الإنتاج إذا تم تعطيل وضع التصحيح.

وفي وظيفتك التغييرات بدلا من

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

هل تجرب

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

في ما يلي مثال واحد عملي على تحميل الملف مع قد يكون تحميل ملف الإفلات بالسحب مفيدًا { http://jsfiddle.net/danielzen/utp7j/

Angular معلومات تحميل الملف

URL لتحميل ملف AngularJS في ASP.Net

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

AngularJs تحميل متعدد الملفات الأصلي مع التقدم مع NodeJS

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

ngUpload - خدمة AngularJS لتحميل الملفات باستخدام iframe

http://ngmodules.org/modules/ngUpload

233
JQuery Guru

لقد قدمت توجيهًا صغيرًا للاستماع إلى تغييرات إدخال الملف.

عرض JSFiddle

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

directive.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();
      });

    }
  };
});
459
sqren

هذا تحسين لبعض البيانات الأخرى الموجودة حولها ، وسوف تنتهي البيانات في نموذج ng ، وهو ما تريده عادة.

توصيف (فقط قم بإنشاء ملف بيانات سمة حتى يتمكن التوجيه من العثور عليه)

<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

الطريقة النظيفة هي كتابة التوجيه الخاص بك لربط "تغيير" الحدث. فقط لإعلامك بأن IE9 لا يدعم FormData ، لذا لا يمكنك الحصول على كائن الملف من حدث التغيير.

يمكنك استخدام ng-file-upload library التي تدعم بالفعل IE مع FileAPI polyfill وتبسيط نشر الملف على الخادم. ويستخدم التوجيه لتحقيق هذا.

<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

لقد قمت بتوسيع فكرةStuart Axon لإضافة ربط ثنائي الاتجاه لإدخال الملف (أي السماح بإعادة تعيين الإدخال عن طريق إعادة تعيين قيمة الطراز إلى قيمة خالية):

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

عرض توضيحي

26
JLRishe

على غرار بعض الإجابات الجيدة الأخرى هنا ، كتبت توجيهًا لحل هذه المشكلة ، لكن هذا التطبيق يعكس بشكل أوثق الطريقة الزاويّة لربط الأحداث.

يمكنك استخدام التوجيه مثل هذا:

HTML

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

كما ترى ، يمكنك حقن الملفات المحددة في معالج الأحداث الخاص بك ، كما يمكنك حقن كائن حدث $ في أي معالج أحداث ng.

جافا سكريبت

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

هذا التوجيه تمرير الملفات المحددة كذلك:

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

    }
  };
});

HTML ، كيفية استخدامه:

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

في وحدة التحكم الخاصة بي:

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

أوصي لإنشاء التوجيه

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

        };
    }]);

يمكن استخدام هذا التوجيه عدة مرات ، ويستخدم نطاقه الخاص ولا يعتمد على نطاق الأصل. يمكنك أيضًا إعطاء بعض المعاملات إلى وظيفة المعالج. سيتم استدعاء وظيفة المعالج باستخدام كائن النطاق ، والتي كانت نشطة عند تغيير الإدخال. قم بتطبيق تحديثات النموذج الخاص بك في كل مرة يتم استدعاء حدث التغيير

6
Julia Usanova

أبسط Angular إصدار 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

العرض التوضيحي العامل لتوجيهات "files-input" التي تعمل مع ng-change1

لجعل عنصر <input type=file> يعمل ng-change التوجيه ، يحتاج إلى توجيه مخصص يعمل مع ng-model التوجيه.

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

التجريبي

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

العناصر الزاوية (مثل العنصر الجذر للتوجيه) هي كائنات 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 ما إذا كان الحدث قد نشأ على عنصر داخلي يطابق المحدد المحدد. إذا حدث ذلك ، فإن المعالج سوف يطلق النار.

فوائد هذه الطريقة هي:

  • يرتبط المعالج بالعنصر $ الذي سيتم تنظيفه تلقائيًا عند إتلاف نطاق التوجيه.
  • لا يوجد كود في القالب
  • ستعمل حتى إذا لم يتم تقديم المفوض المستهدف (الإدخال) بعد عند تسجيل معالج الأحداث (مثل عند استخدام ng-if أو ng-switch)

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

0
Matt S

لقد فعلت ذلك مثل هذا ؛

<!-- 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

يمكنك ببساطة إضافة الكود أدناه في onchange وسوف يكتشف التغيير. يمكنك كتابة وظيفة عند النقر على X أو أي شيء لإزالة بيانات الملف ..

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

قاعدة حل كاملة للغاية على:

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

هناك طريقة بسيطة لإخفاء حقل الإدخال واستبداله بالصورة ، هنا بعد حل ، والتي تتطلب أيضًا اختراقًا للزاوية ولكنها تؤدي المهمة [TriggerEvent لا يعمل كما هو متوقع]

الحل:

  • ضع حقل الإدخال في الشاشة: لا يوجد [حقل الإدخال موجود في 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!!!
    };
0
Fulup

هناك طريقة أخرى مثيرة للاهتمام للاستماع إلى تغييرات إدخال الملف وهي مراقبة السمة ng الخاصة بملف الإدخال. خارج مسار FileModel هو توجيه مخصص.

مثله:

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

كود JS ->

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

آمل أن يساعد شخص ما.

0
halbano