Ko.applybindings not working with dynamic html element
I am writing some code where when the user clicks on the add file button, after success add a new row to the table that includes the upload button. This button will bind to the client of the data binding.
I am trying to apply knockoutbindings to a dynamic html string. without any consequences. From my code, I am not getting any error, but nothing happens after clicking the download button.
code
ViewModel
$(function () {
// download section viewModel
var viewModel = function () {
self.downloadOrder = function (item, event) {
var domElement = event.target;
$.fileDownload('@Url.Action("test", "test")' + "?fileName=" + item.documentName + ""eNoEncrypted=" + item.quoteNoEncrypt, {
failCallback: function () {
$("<span style='position: absolute'> @TranslationService.Read("Waybill_Common_FileNoLongerExist", module, languageCode) </span>").insertAfter(domElement).fadeIn(1000, "linear", function () {
$(domElement).next().delay(2000).fadeOut("slow");
});
}
});
};
}
Bindings when loading source document
ko.applyBindings(viewModel, document.getElementById("documentSection"));
ko.applyBindings(headerViewModel, document.getElementById("dashBoardHeader"));
ko.applyBindings(quoteVM, document.getElementById("viewRequest"));
after successful upload add row to docs table and applybindings. Issue.
$("#btncareerssubmimt").click(function () {
$("#uploadDocumentForm").ajaxSubmit({
type: "POST",
success: function (data) {
$.each(data, function (index, file) {
// insert new datafile row to the table
$("#supporting-documents-table >tbody:last").append('<tr id=' + file.DocumentId + '><td>' + file.Title + '</td>' + '<td>' +
file.UploadDate + '</td>' + '<td>' + '<input type="button" value="@TranslationService.Read("Waybill_Common_DownloadTitle", module, languageCode)" data-bind="click: function(data, event){downloadOrder({quoteNoEncrypt: "@Model.QuoteNoEncrypt", documentName:' +
file.Title + '}, event)}" />' + '</td></tr>');
// get new row id
var rowId = $("#supporting-documents-table tr:last").attr('id');
// add the download knockout handler to this new row
ko.applyBindings(viewModel, document.getElementById(rowId));
})
}):
any ideas? thank.
source to share
You need to re-bind the bindings, for example:
var element = document.getElementById("documentSection");
ko.cleanNode(element);
ko.applyBindings(viewModel, element);
But I am not suggesting doing this, as far as I remember, it is not well supported (since it does not clear the event handlers).
The correct way to do this would be to have observableArray
your supporting documents, and if you need to add logic to iterate over, think of an array and display your strings, but on success
you just need to add a new object to that observableArray
and the string will be added automatically. (a good example can be found there ).
source to share
Thanks to Vladimir's guidance, the problem was solved with observable arrays.
I added the uploadDocument function to the existing viewModel
uploadDocument: function (documentList) {
if (documentList != null) {
_uploadButtonDisable(true)
// start spinner
var target = document.getElementById('uploadMessage');
var spinner = new Spinner().spin(target);
//show spinner
$(target).val("").show();
$("#uploadDocumentForm").ajaxSubmit({
type: "POST",
success: function (data) {
$.each(data, function (index, file) {
// insert new datafile row to the table
documentList.push(file);
spinner.stop(spinner);
$("#uploadMessage").text('@TranslationService.Read("SSP_Common_Success_Text", "SSP", languageCode)').fadeIn(1000, "linear", function () {
$(this).delay(2000).fadeOut("slow", function () {
$(this).text("");
});
});
_uploadButtonDisable(false)
})
},
error: function () {
spinner.stop(spinner);
$("#uploadMessage").text('@TranslationService.Read("SSP_Server_Error_UI_Text", "SSP", languageCode)').fadeIn(1000, "linear", function () {
$(this).delay(2000).fadeOut("slow", function () {
$(this).text("");
});
});
_uploadButtonDisable(false)
//input.replaceWith(input.val('').clone(true));
}
});
var input = $("#choose-file");
}
}
Bind the viewModel.
var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
var mvcwModel = ko.mapping.fromJSON(jsonModel);
mvcwModel.viewModel = viewModel;
ko.applyBindings(mvcwModel, document.getElementById("viewRequest"));
attach uploadDocument to uploadButton
<tr>
<td>
<th><input type="button" value="@TranslationService.Read("Waybill_OrderDisplay_UploadSubmit", module, languageCode)" id="btncareerssubmimt" class=" floatRight" data-bind="disable: viewModel.uploadButtonDisable, click: function(){ viewModel.uploadDocument($root.Documents);}" /></th>
</td>
</tr>
source to share