显示 AngularJS 中的 <input> 中的选定文件

Displaying a selected file from an <input> in AngularJS

我有一个使用标准 Javascript 的工作示例,但我想使用 AngularJS 使它更自然地工作。

具体来说,我需要用用户选择的文件的文件名更新跨度。

这是我使用本机实现的 Javascript:

<span>
    <input  ng-model="uploadDownloads" type="file" style="visibility:hidden; width: 1px;" id=uploadDownloads name=uploadDownloads onchange="$(this).parent().find('span').html($(this).val().replace('C:\fakepath\', ''))"  /> <!-- Chrome security returns 'C:\fakepath\'  -->
    <input  class="btn btn-primary" type="button" value="choose file" onclick="$(this).parent().find('input[type=file]').click();"/> <!-- on button click fire the file click event -->
    <span  class="badge badge-important" ></span>
</span> 

文件读取器函数已经在 angular 中了:

$scope.add = function(valid){
        if(valid){
                $scope.data = 'none';
                var f = document.getElementById('uploadDownloads').files[0];
                var r = new FileReader();
                r.onloadend = function(e){
                    $scope.data = e.target.result;
                    $scope.notPass = false;
                    $modalInstance.close({
                        'data':$scope.data,
                        'fileName':$scope.fileName,
                        'fileExplain':$scope.fileExplain
                    });
                };
            /*activate the onloadend to catch the file*/
                r.readAsBinaryString(f);
        } else {
            $scope.notPass = true;
        }
    };

问题是用 Angular 而不是 JavaScript 来激活 onclick 和 onchange,这样我的 <span> 就会更新为选定的文件名。

此问题建立在现有 question and answer. Specifically, however, I have modified the code from that answer 的基础上,以解决此处似乎是特定问题的问题,即您如何更新 <span> 以让用户以某种方式选择文件名这是 angularjs.

的惯用语

这是一个 codepen 的工作示例。

这是 html 文件的相关部分:

<body ng-controller="AppController">
    <input ng-model="uploadDownloads" type="file" fd-input file-name="fileName"/> 
    <span class="badge badge-important">Output here: {{fileName}}</span>
</body>

这里的关键是您有一个名为 fd-input 的自定义指令,它具有到它定义的名为 file-name 的属性的双向绑定。您可以将 $scope 变量之一传递给该属性,该指令会将文件名绑定到它。这是控制器和指令。

(function() {
  'use strict';

  angular.module('app', [])
    .controller('AppController', AppController)
    .directive('fdInput', fdInput);

  function AppController($scope) {
    $scope.fileName = '';
  }

  function fdInput() {
    return {
      scope: {
        fileName: '='
      },
      link: function(scope, element, attrs) {
        element.on('change', function(evt) {
          var files = evt.target.files;
          console.log(files[0].name);
          console.log(files[0].size);

          scope.fileName = files[0].name;
          scope.$apply();
        });
      }
    }
  };

})();

如上所述,指令直接取自another SO answer。我修改了它以添加一个范围,该范围可以通过两种方式绑定到 file-name 属性:

...
return {
  scope: {
    fileName: '='
  },
...

然后我将 files[0].name 分配给双向绑定:

...
scope.fileName = files[0].name;
scope.$apply();
...

查看codepen。应该这样做。您可以只在指令中使用父作用域,但这不是一个好主意,因为它限制您对每个控制器使用一次该指令。此外,如果您想列出多个文件,则必须将此代码更新为 return 这些文件的数组。

希望对您有所帮助。