我尝试使用ng-model的输入标签类型文件:

<input type="file" ng-model="vm.uploadme" />

但是在选择了一个文件后,在控制器中,$scope.vm。Uploadme仍然没有定义。

我如何在我的控制器中获得所选文件?


当前回答

function filesModelDirective(){
  return {
    controller: function($parse, $element, $attrs, $scope){
      var exp = $parse($attrs.filesModel);
      $element.on('change', function(){
        exp.assign($scope, this.files[0]);
        $scope.$apply();
      });
    }
  };
}
app.directive('filesModel', filesModelDirective);

其他回答

我必须在多个输入上做同样的事情,所以我更新了@Endy Tjahjono方法。 它返回一个包含所有已读文件的数组。

  .directive("fileread", function () {
    return {
      scope: {
        fileread: "="
      },
      link: function (scope, element, attributes) {
        element.bind("change", function (changeEvent) {
          var readers = [] ,
              files = changeEvent.target.files ,
              datas = [] ;
          for ( var i = 0 ; i < files.length ; i++ ) {
            readers[ i ] = new FileReader();
            readers[ i ].onload = function (loadEvent) {
              datas.push( loadEvent.target.result );
              if ( datas.length === files.length ){
                scope.$apply(function () {
                  scope.fileread = datas;
                });
              }
            }
            readers[ i ].readAsDataURL( files[i] );
          }
        });

      }
    }
  });

对于使用lodash或下划线输入的多个文件:

.directive("fileread", [function () {
    return {
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            element.bind("change", function (changeEvent) {
                return _.map(changeEvent.target.files, function(file){
                  scope.fileread = [];
                  var reader = new FileReader();
                  reader.onload = function (loadEvent) {
                      scope.$apply(function () {
                          scope.fileread.push(loadEvent.target.result);
                      });
                  }
                  reader.readAsDataURL(file);
                });
            });
        }
    }
}]);

或者你可以获取输入并设置onchange函数:

<input type="file" id="myFileInput" />
document.getElementById("myFileInput").onchange = function (event) {
   console.log(event.target.files);                        
};

这是@endy-tjahjono解决方案的补充。

我最终无法从作用域获得uploadme的值。即使在HTML中的uploadme被指令明显地更新了,我仍然不能通过$scope.uploadme访问它的值。不过,我可以从作用域设置它的值。神秘的,对吧?

结果是,该指令创建了一个子作用域,并且子作用域有自己的uploadme。

解决方案是使用对象而不是原语来保存uploadme的值。

在控制器中我有:

$scope.uploadme = {};
$scope.uploadme.src = "";

在HTML中:

 <input type="file" fileread="uploadme.src"/>
 <input type="text" ng-model="uploadme.src"/>

指令没有变化。

现在,一切都像预期的那样。我可以获取uploadme的值。SRC从我的控制器使用$scope.uploadme。

这是一个稍微修改过的版本,允许你在作用域中指定属性的名称,就像你在ng-model, usage中所做的一样:

    <myUpload key="file"></myUpload>

指令:

.directive('myUpload', function() {
    return {
        link: function postLink(scope, element, attrs) {
            element.find("input").bind("change", function(changeEvent) {                        
                var reader = new FileReader();
                reader.onload = function(loadEvent) {
                    scope.$apply(function() {
                        scope[attrs.key] = loadEvent.target.result;                                
                    });
                }
                if (typeof(changeEvent.target.files[0]) === 'object') {
                    reader.readAsDataURL(changeEvent.target.files[0]);
                };
            });

        },
        controller: 'FileUploadCtrl',
        template:
                '<span class="btn btn-success fileinput-button">' +
                '<i class="glyphicon glyphicon-plus"></i>' +
                '<span>Replace Image</span>' +
                '<input type="file" accept="image/*" name="files[]" multiple="">' +
                '</span>',
        restrict: 'E'

    };
});