简体   繁体   English

如何使用ng-model双向绑定到type =“ file”输入?

[英]How do I two-way bind to a type=“file” input with ng-model?

Basically I want to do this: 基本上我想这样做:

<input type="file" ng-model="variable_in_scope">

When I pick a file, variable_in_scope should get assigned to the file object picked. 当我选择一个文件时, variable_in_scope应该分配给所选择的文件对象。 Also, if the value of variable_in_scope gets changed anywhere else in my page, it should update the text next to the "Choose File" button to indicate that the chosen file has changed. 另外,如果variable_in_scope的值在我页面的其他位置更改了,它应该更新“选择文件”按钮旁边的文本以指示所选文件已更改。

With any other type of input, this would just work. 使用任何其他类型的输入,这将起作用。

I don't need to do anything fancy like actually see the contents of the file. 我不需要做任何花哨的操作,例如实际看到文件的内容。 Ultimately, I want to post it, but I've found out you can do this by setting the file object you get into a FormData object , without actually reading the contents into Javascript-land. 最终,我想发布它,但是我发现您可以通过将获取到FileData对象的文件对象设置为FormData对象来完成此操作,而无需将内容实际读入Javascript领域。

I've found other questions about picking files with angular, but none had a two-way binding solution. 我还发现了其他有关选择角度文件的问题,但是没有一个双向绑定解决方案。

My answer on another question provides a way to do this with ng-model , but since that question is not specifically about two way binding (and my answer is fairly hard to find there), I'll reproduce it here: 对另一个问题的回答提供了使用ng-model做到这一点的方法,但是由于该问题不是专门针对双向绑定的(我的回答在那儿很难找到),因此我将在此处进行重现:

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 演示

To use it, you simply need to add this to your angular module and include a bind-file attribute on the file pickers where you want to use it. 要使用它,您只需要将其添加到您的angular模块中,并在您要使用它的文件选择器中包含bind-file属性。

Angular doesn't support binding to file-type inputs , but I cobbled together a solution using a number of other answers. Angular不支持绑定到文件类型的输入 ,但是我使用许多其他答案将解决方案拼凑在一起。

app.directive('filePicker', filePicker);

filePicker.$inject = ['$log', '$document'];

function filePicker($log,$document) {

  var directive = {
    restrict: 'A',
    require: 'ngModel',
    scope: {
      ngModel: '='
    },
    link: _link
  };

  return directive;

  function _link(scope, elem, attrs, ngModel) {

    // check if valid input element
    if( elem[0].nodeName.toLowerCase() !== 'input' ) {
      $log.warn('filePicker:', 'The directive will work only for input element, actual element is a', elem[0].nodeName.toLowerCase());
      return;
    }

    // check if valid input type file
    if( attrs.type != 'file' ) {
      $log.warn('filePicker:', 'Expected input type file, received instead:', attrs.type, 'on element:', elem);
      return;
    }

    // listen for input change
    elem.on('change', function(e) {

      // get files
      var files = elem[0].files;

      // update model value
      scope.$apply(function() {
          attrs.multiple ? scope.ngModel = files : scope.ngModel = files[0];
      });
    });

    scope.$watch('ngModel', function() {
        if (!scope.ngModel)
            elem[0].value = ""; // clears all files; there's no way to remove only some
    });

  }

}

This solution showed me how to use a directive to implement a custom binding to ng-model. 该解决方案向我展示了如何使用指令来实现对ng-model的自定义绑定。 It enables accessing the contents of the file, so if you need that functionality you can add it back to my solution. 它使您能够访问文件的内容,因此,如果需要该功能,可以将其重新添加到我的解决方案中。

However, it had some problems with its binding. 但是,它的绑定存在一些问题。 It would correctly set the value of my variable_in_scope , but if there were other things bound to the value of variable_in_scope , they wouldn't update. 它将正确设置我的variable_in_scope的值,但是如果variable_in_scope的值绑定了其他内容,则它们不会更新。 The trick was to use isolate scope and $apply . 诀窍是使用隔离范围和$apply Then you don't need to mess with this $setViewValue business. 这样,您就不必为此$setViewValue业务搞乱了。 Just set it and forget it. 只需设置它,然后忘记它。

That got me as far as one-way-binding. 那使我达到了单向绑定的目的。 If I set a value to variable_in_scope , however, the file picker still showed that I had the original file selected. 但是,如果将值设置为variable_in_scope ,则文件选择器仍显示我已选择原始文件。 In my case all I really want to do is clear the selected file. 就我而言,我真正想做的就是清除所选文件。 I found out the Javascript magic to do this and set up a $watch on the ngModel to trigger it. 我发现了执行此操作的Javascript魔术,并ngModel上设置了一个$watch来触发它。

If you want to set the file to a different value programmatically, good luck to you, because FileList is read-only . 如果要通过编程将文件设置为其他值,请祝您好运,因为FileList是只读的 The magic trick lets you clear the FileList , but you can't add anything back. 魔术使您可以清除FileList ,但不能添加任何内容。 Maybe you can create a new FileList and assign it to .files , but at a cursory glance I didn't see a way to do that. 也许您可以创建一个新的FileList并将其分配给.files ,但是粗略地看一眼,我看不到这样做的方法。

Helped for me: FileUploader 对我有帮助: FileUploader

Hide the input element with display: none; 使用display隐藏输入元素:none; then use a label to go on top of the input element, and a label you connect to your scope variable. 然后使用标签放在输入元素的顶部,然后使用标签连接到范围变量。 See numerous posts on SO. 在SO上看到许多帖子。 Like this: 像这样:

<label for="idFileUpload" class="custom-file-upload">
    SelectFile
</label>
<input type="file" id="idFileUpload" nv-file-select uploader="uploader">
<label id="idSelectedFile">{{selectedFile}}</label>
<md-button id="idUploadBtn" md-no-ink class="md-primary settingsBtns" ng-click="uploader.uploadAll()" ng-disabled="!uploader.getNotUploadedItems().length">Upload</md-button>

CSS: CSS:

input[type="file"] {
    display: none;
}

.custom-file-upload {
    background-color: green;
    color: white;
    border: 1px solid #ccc;
    display: inline-block;
    padding: 6px 12px;
    cursor: pointer;
}

In the events the FileUploader fires, you can fetch the value of the input element. 在FileUploader触发的事件中,您可以获取输入元素的值。 HTH HTH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何更新k-ng-model(也称为与ng-model相似的双向绑定) - How to update k-ng-model (a.k.a. two-way binding like with ng-model) ng-model和标准双向数据绑定之间有什么区别? - What's the difference between ng-model and standard two-way data binding? 如何在双向数据绑定中使用ng-bind-html? - How to use ng-bind-html with two-way databinding? 如何在angularjs中的两个不同的ng-model之间绑定数据 - How to bind data between two different ng-model in angularjs 绑定输入并选择一个ng模型 - Bind input and select to one ng-model 如何将选定的颜色绑定到ng模型? - How do bind a chosen color to an ng-model? 单击按钮时将ng-model分配给输入类型文件 - To assign ng-model to the input type file when clicking the button 如何将ng-model属性绑定到动态生成的jQuery元素? - How do I bind ng-model attribute to jQuery element which is generated dynamically? 如何使用Angular js上传图像? 或如何在输入类型文件中使用/模拟ng-model? - how to upload images with Angular js ? or how to use / simulate ng-model in input type file? 是否可以在不使用 ng-model 和 ng-bind 的情况下实现 angular 的双向数据绑定? - Is it possible to achieve two way data binding in angular without using ng-model and ng-bind?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM