TL;DR: I need to set a default value for display on a select2 field, bound via knockout, but the select2 binding keeps overriding my viewmodel value to "" instead of accepting the value.
I am utilizing the following:
Start()
function""
when it loads, as a value hasn't been selected yet -- rather than letting me show a default item based on my bound value..I'll be investigating all of these:
Document Load
$(document).ready(function () {
'use strict';
console.log("creating viewmodel");
vm = new invoiceDetailsPage.ViewModel();
vm.Start();
console.log("applying bindings");
ko.applyBindings(vm);
});
The invoiceDetailsPage NameSpace(some irrelevant parts removed)
var invoiceDetailsPage = invoiceDetailsPage || {
InvoiceDetailItem: function () {
'use strict';
var self = this;
self.DatePayable = new Date();
self.Fees = 0.00;
self.Costs = 0.00;
self.Adjustments = ko.observable();
self.AdjustmentNote = ko.observable();
self.Total = ko.computed(function () {
});
self.hasAdjustments = ko.computed(function () {
});
},
Invoice: function (invoiceID, documentTypeID, firmID, invoiceNumber, invoicePeriod, datePayable, privateComment, statusID, vendorFirmID) {
'use strict';
var self = this;
self.TypeID = ko.observable(documentTypeID);
self.PrivateComment = ko.observable(privateComment);
self.Status = ko.observable(statusID);
self.FirmID = ko.observable(firmID);
self.VendorFirmID = ko.observable(vendorFirmID);
self.InvoicePeriod = ko.observable(invoicePeriod);
self.DatePayable = ko.observable(datePayable);
self.InvoiceNumbers = ko.observable(invoiceNumber);
self.DetailItems = ko.observableArray([]);
self.isFinalized = ko.computed(function () {
//finalized if it has the appropriate status (anything except)
});
self.hasPrivateComments = ko.computed(function () {
// if self.privatecomment isn't null or empty, true
});
self.TotalFees = ko.computed(function () {
//foreach item in detailitems, sum of fees.
});
self.TotalCosts = ko.computed(function () {
//foreach item in detailitems, sum of Costs.
});
self.TotalAdjustments = ko.computed(function () {
//foreach item in detailitems, sum of adjustments.
});
self.GrandTotal = ko.computed(function () {
//foreach item in detailitems, sum of totals.
});
},
LoadInvoice: function (clientSiteID, invoiceID, callbackFunction, errorFunction) {
'use strict';
var self = this;
self.clientSiteID = clientSiteID;
self.invoiceID = invoiceID;
$.ajax({
url: '/api/DefenseInvoice/GetDefenseInvoice?ClientSiteID=' + self.clientSiteID + "&InvoiceID=" + invoiceID,
type: 'GET',
processData: false,
contentType: 'application/json; charset=utf-8',
dataType: "json",
data: null,
success: function (data) {
console.log(data);
callbackFunction(data);
},
error: function (jqXHR, textStatus, errorThrown) {
errorFunction(jqXHR, textStatus, errorThrown);
}
});
},
ViewModel: function () {
'use strict';
var self = this;
self.InvoiceLoaded = ko.observable();
self.Invoice = ko.observable(new invoiceDetailsPage.Invoice()); // load blank invoice first
self.clientSiteID = -1;
self.invoiceID = -1;
self.SaveInvoiceDetails = function () {
// can only save the details prior to approval / rejection
// should update only general invoice fields, not private comments or adjustments
};
self.LoadInvoice = function() {
self.InvoiceLoaded(false);
invoiceDetailsPage.LoadInvoice(self.clientSiteID, self.invoiceID, function(result) {
//success
vm.Invoice(new invoiceDetailsPage.Invoice(
result.InvoiceInfo.DefenseInvoiceID,
result.InvoiceDocumentTypeID,
result.InvoiceInfo.FirmID,
result.InvoiceInfo.InvoiceNumber,
result.InvoiceInfo.InvoicePeriod,
result.InvoiceInfo.DatePayable,
result.InvoiceInfo.PrivateComment,
result.InvoiceInfo.StatusID,
result.InvoiceInfo.VendorFirmID
));
self.InvoiceLoaded(true);
}, function() {
//error
toastr.error("We're sorry, but an error occurred while trying to load the invoice. Please contact support or refresh the page to try again.", "Invoice Approval");
console.log("LoadInvoice -- ERROR");
console.log(" error: " + errorThrown);
toastr.clear(notifier);
});
};
self.Start = function () {
self.LoadInvoice();
};
},
utils: {
GetSelect2Options: function (placeholder, url) {
'use strict';
var options = {
allowClear: false,
placeholder: placeholder,
query: function (query) {
var dto = {
query: query.term,
filters: {
ClientSiteID: Number(vm.clientSiteID)
}
};
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(dto),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
query.callback(msg);
}
});
}
};
return options;
}
}
};
The Knockout Binding we're using
ko.bindingHandlers.select2 = {
init: function (element, valueAccessor, allBindingsAccessor) {
var obj = valueAccessor(),
allBindings = allBindingsAccessor(),
lookupKey = allBindings.lookupKey;
$(element).select2(obj);
if (lookupKey) {
var value = ko.utils.unwrapObservable(allBindings.value);
$(element).select2('data', ko.utils.arrayFirst(obj.data.results, function (item) {
return item[lookupKey] === value;
}));
}
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).select2('destroy');
});
},
update: function (element) {
$(element).trigger('change');
}
};
The HTML Element and its bindings
<input type="text" id="ddlInvoiceType" placeholder="Invoice Type" class="select2-container" data-bind="select2: invoiceDetailsPage.utils.GetSelect2Options('Invoice Type', '/api/DefenseInvoiceType/Post'), value: Invoice().TypeID"/>
Not sure I understood the question properly, at first I see the possible issue in the update part of the custom binding:
update: function (element, valueAccessor) {
//added next row to update value
$(element).val(ko.utils.unwrapObservable(valueAccessor()));
$(element).trigger("change");
}
I got it working and I think the difference is in the init with an select like
<input type="hidden" class=""
data-bind="value: observedValue, select2: --your options--">
Here is mine:
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).select2('destroy');
});
select2 = ko.utils.unwrapObservable(allBindings().select2);
$(element).select2(select2);
},
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With