Reputation: 21275
I am setting up a Knockout array where a person can add in multiple items, each with the option to upload a file attachment. I have the buttons working and I can upload a file from anywhere in the DOM, but now I need to know which upload button was clicked so I can attach the file information to right array item. Each button has it's own ID
. Any thoughts as to how I determine this?
I am not sure if I can do a jsFiddle with uploadify. Here is the source:
function PetOwner() {
var self = this;
self.FirstName = ko.observable('');
self.MiddleName = ko.observable('');
self.LastName = ko.observable('');
self.Address = ko.observable('');
self.City = ko.observable('Mankato');
self.State = ko.observable('MN');
self.ZipCode = ko.observable('56001');
self.HomePhone = ko.observable('');
self.WorkPhone = ko.observable('');
self.MobilePhone = ko.observable('');
self.Email = ko.observable('');
self.Pets = ko.observableArray([new PetVM()]);
self.Message = ko.observable('');
// Add an additional pet to the application
self.AddPet = function () {
self.Pets.push(new PetVM());
$("input[type=file]").uploadify(uploadifyConfig);
};
}
// Individual pet view model (included in AnimalLicenseVM)
function PetVM() {
var self = this;
self.Type = ko.observable('');
self.Name = ko.observable('');
self.Sex = ko.observable('');
self.Breed = ko.observable('');
self.SpayedOrNeutered = ko.observable('');
self.Age = ko.observable('');
self.Color = ko.observable('');
self.Marks = ko.observable('');
self.RabiesTag = ko.observable('');
self.DateOfVacc = ko.observable('');
self.Expiration = ko.observable('');
self.Microchip = ko.observable('');
self.ImgUrl = ko.observable('');
}
var uploadifyConfig = {
'swf': "/jquery/uploadify/uploadify.swf",
'uploader': "/my/uploader/",
'fileTypeDesc': 'Image Files',
'fileTypeExts': '*.gif; *.jpg; *.png',
'fileSizeLimit': '5MB',
'buttonText': 'Choose Image',
'scriptAccess': 'always',
'uploadLimit': 1,
'height': 20,
'width': 100,
//'buttonClass': 'uploadify-button',
'onUploadSuccess': function (file, data, response) {
var json = jQuery.parseJSON(data);
if (json.IsSuccessful) {
// TODO
} else {
alert(json.Message);
}
}
}
Here is the relevant HTML.
<div class="pet-row" data-bind="foreach: Pets">
<input class="required" type="text" title="Please include a pet name" data-bind="value: Name, uniqueName: true" />
<input type="file" accept="image/*" class="fileUpload" data-bind="attr: {id: 'petFile-' + $index() }" />
<input type="hidden" data-bind="value: ImgUrl, uniqueName: true" />
</div>
Upvotes: 0
Views: 236
Reputation: 21275
The only problem with @Ilya Luzyanin answer was that Uploadify uses flash, thus a click event didn't work.
He did get me going down the right path however. Here is what I had to do:
PetOwner()
alone. I didn't have to modify it.PetVM()
and called it self.UploadifyConfig
which contained my configuration.onUploadSuccess()
method in the UploadifyConfig
I was then able to use self.ImgUrl
.update
as init
didn't have the id yet at the time of initialization. My bindingHandler:
ko.bindingHandlers.uploadify = {
update: function (element, valueAccessor) {
if ($(element).attr('id') !== '') {
$(element).uploadify(valueAccessor());
}
}
};
Complete PetVM()
function PetVM() {
var self = this;
self.Type = ko.observable('');
self.Name = ko.observable('');
self.Sex = ko.observable('');
self.Breed = ko.observable('');
self.SpayedOrNeutered = ko.observable('');
self.Age = ko.observable('');
self.Color = ko.observable('');
self.Marks = ko.observable('');
self.RabiesTag = ko.observable('');
self.DateOfVacc = ko.observable('');
self.Expiration = ko.observable('');
self.Microchip = ko.observable('');
self.ImgUrl = ko.observable('');
self.UploadifyConfig = {
'swf': "/jquery/uploadify/uploadify.swf",
'uploader': "/my/uploader/",
'fileTypeDesc': 'Image Files',
'fileTypeExts': '*.gif; *.jpg; *.png',
'fileSizeLimit': '5MB',
'buttonText': 'Choose Image',
'scriptAccess': 'always',
'uploadLimit': 1,
'height': 20,
'width': 100,
//'buttonClass': 'uploadify-button',
'onUploadSuccess': function (file, data, response) {
var json = jQuery.parseJSON(data);
if (json.IsSuccessful) {
self.ImgUrl(json.Message);
} else {
alert(json.Message);
}
}
}
}
I hope this helps others in the future.
Upvotes: 0
Reputation: 8110
First of all, I would suggest you to move uploadify
initialization to a custom binding handler, because currently you're initializing all file inputs each time new pet is added and also it's as a good practice to not mix DOM manipulation with view model. So your custom binding handler could look something like this:
(function(ko, $) {
ko.bindingHandlers.uploadify = {
init: function(element, valueAccessor) {
console.log($(element).attr('id') + ' is initialized');
// Here should be your initialization of
// uploadify, something like $(element).uploadify(valueAccessor());
}
}
})(ko, jQuery);
And in markup something like:
<input type="file" data-bind="click: $parent.signalUpload, attr: {'id': id}, uploadify: $parent.uploadifyConfig" />
I used simplified version of view model, just to demonstrate how to determine which upload button was clicked:
function ViewModel() {
var self = this;
self.counter = 1;
self.buttons = ko.observableArray([]);
self.addNewItem = function() {
self.buttons.push({id : self.counter, name: 'New item ' + self.counter++});
};
self.signalUpload = function(data) {
console.log(data.name);
return true;
};
self.uploadifyConfig = {};
}
When clicking upload button, console will log current item's name, which it receives from data
parameter, which is passed to click callback.
Upvotes: 1