I have a knockout viewmodel getting populated from a JSON call.
In a select element in a form, I have a set of options (also coming from viewmodel) and the value, part of observableArray
.
The issue is only with the select element and not with input ones -- when submitting the form, only the values that have been assigned to in select contain proper values. So the ones that have been successfully loaded from JSON and presented in form, but left unchanged, will be sent back to server as the first value from the options array.
HTML Form:
<form>
<table >
<thead>
...
</thead>
<tbody data-bind='foreach: ScaledCostEntries'>
<tr>
<td><input data-bind='value: StartDateString' class="startdate" type="text"/></td>
<td><select data-bind='value: InvoiceType, options: $root.InvoiceTypes'></select></td>
<td><a href='#' data-bind='click: $root.removeCost'>Delete</a></td>
</tr>
</tbody>
</table>
<button data-bind='click: addCost'>Add New Row</button>
<button data-bind='click: save' >Update</button>
</form>
In this code above the problem is with InvoiceType, part of the viewmodels ScaledCostEntries
observableArray. (Also, if I swap the order of value and options, that will not put a selected value in the select element).
and the JS:
<script type="text/javascript">
$(function () {
var scaledCostModel = function () {
var self = this;
self.ScaledCostEntries = ko.observableArray([]);
self.InvoiceTypes = ko.observableArray([]);
self.addCost = function () {
self.ScaledCostEntries.push({
StartDateString: ko.observable(),
InvoiceType: ko.observable()
});
};
self.removeCost = function (cost) {
cost.IsDeleted = true;
self.ScaledCostEntries.destroy(cost);
};
self.save = function (form) {
jQuery.ajax({
url: '@Request.Url.PathAndQuery',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: ko.toJSON(self.ScaledCostEntries)
});
};
};
jQuery.getJSON('@Request.Url.PathAndQuery', function (data) {
ko.mapping.fromJS(data, {}, viewModel);
});
var viewModel = new scaledCostModel();
ko.applyBindings(viewModel);
});
</script>
So, to summarize, the issue is with viewmodel's property bound to a select element. When the select is left unchanged (not reselected), the viewmodel will have it's value as the first item from the options (InvoiceTypes
) array, when posting to server.
In the end, I might be forgetting something trivial and this is my first more serious knockout.js attempt.
Note: InvoiceType
is part of the ScaledCostEntries
, which is observableArray
.
InvoiceTypes
is observableArray
.
Both InvoiceTypes
and ScaledCostEntries
, come from JSON and ScaledCostEntries
is sent back.