如何在初始化 jQuery fileupload 后将 knockout js 绑定重新应用到文件输入元素?

How do I reapply knockout js bindings to a file input element after initializing jQuery fileupload?

我设置了一个 viewModel,它从文本输入中获取宽度和高度。我想将该宽度和高度传递给文件输入上的数据宽度和数据高度属性。

我正在使用 jQuery.fileupload.js 来处理文件上传过程。我看到的问题是,在您将文件添加到文件输入后,当文本输入更改时,数据属性的绑定不再更新。

html

<input id="file" type="file" data-bind="attr:{'data-height': height, 'data-width': width}" /><br />
<input type="text" data-bind="textInput: width" /><br />
<input type="text" data-bind="textInput: height" />

脚本

var ViewModel = function(width, height) {
  this.width = ko.observable(width);
  this.height = ko.observable(height);
};

ko.applyBindings(new ViewModel(300, 300));

var $file = $('#file');
$file.fileupload({
    add: function(){
    ko.cleanNode($file[0]);
    ko.applyBindings(ViewModel, $file[0]);
  },
  change: function(e, data) {
    ko.cleanNode($file[0]);
    ko.applyBindings(ViewModel, $file[0]);
  }
});

https://jsfiddle.net/jrwdev/1n9ye60z/3/

当输入元素更新时,如何确保绑定保留或至少重新绑定到文件输入?

您看到此行为是因为 jQuery.fileupload.jsreplaceFileInput 选项:

By default, the file input field is replaced with a clone after each input field change event.
This is required for iframe transport queues and allows change events to be fired for the same file selection, but can be disabled by setting the following option to false:
replaceFileInput: true

因此,任何 Knockout 绑定都不会(再)应用于此克隆。

下面的示例有一个额外的 title 绑定绑定到视图模型的 width 属性 上载按钮(作为它的工具提示)表明这不仅影响绑定data-属性。

请注意,将 replaceFileInput 设置为 false,选择文件后 title 仍会更新。

请注意,只有在您的应用程序不需要 iframe 传输队列的情况下才能应用它。

var ViewModel = function(width, height) {
    this.width = ko.observable(width);
    this.height = ko.observable(height);
};

var $file = $('#file');
$file.fileupload({
    replaceFileInput: false
});

ko.applyBindings(new ViewModel(300, 300));
<script src="https://dev4.promotionpod.com/static/scripts/jquery-1.12.4.min.js"></script>
<script src="https://dev4.promotionpod.com/static/internal/uploader/js/vendor/jquery.ui.widget.js"></script>
<script src="https://dev4.promotionpod.com/static/internal/uploader/js/jquery.iframe-transport.js"></script>
<script src="https://dev4.promotionpod.com/static/internal/uploader/js/jquery.fileupload.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<input id="file" type="file" data-bind="attr:{'data-height': height, 'data-width': width, title: width}" /><br />
<input type="text" data-bind="textInput: width" /><br />
<input type="text" data-bind="textInput: height" />