Reputation: 1176
I've got a viewModel set up that gets the width and height from text inputs. I want to pass that width and height to the data-width and data-height attributes on the file input.
I'm using jQuery.fileupload.js to handle the file upload process. The issue I'm seeing is that after you've added a file to the file input, the bindings to the data attributes no longer update when the text inputs are changed.
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" />
scripts
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/
How can I ensure that the bindings stay or are at least re-bound to the file input when the input element gets updated?
Upvotes: 0
Views: 717
Reputation: 23314
You see this behaviour because of the replaceFileInput
option of jQuery.fileupload.js
:
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
Because of this, any Knockout bindings don't get applied (anymore) on this clone.
The example below has an additional title
binding bound to the viewmodel's width
property on the upload button (being its tooltip) to show that this doesn't only affect bound data-
attributes.
Notice that with replaceFileInput
set to false
, the title
still updates after having chosen a file.
Be aware that you can only apply this in case your application doesn't need iframe transport queues.
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" />
Upvotes: 1