Reputation: 2252
I have viewmodel with an array of diagnosis codes. In my html I have a button data-bound to a click that adds a blank diagnosis code to the array. This all works.
I use the button to add diagnosis codes. This works.
I am receiving JSON from an external source, and then trying to wrap it in an observable. Because it is from an external source, it does not have functions that I can bind to, so I am binding to functions that are not part of viewModel.
When I try to convert the object back to a JSON string, the new diagnosis codes are empty strings (the default value I add when the new codes).
Here's the code:
<h3>Diagnosis Codes<input type="button" value="Add" data-bind="click:AddDiagnosisCode"/></h3>
<div data-bind="foreach:DiagnosisCodes">
<div><input type="text" data-bind="value:$data"/><input type="button" value="Remove" data-bind="click: function(data, event) { RemoveDiagnosisCode($parent, data, event) }"/>
</div>
</div>
<script type="text/javascript">
function AddDiagnosisCode(item)
{
item.DiagnosisCodes.push("");
}
function RemoveDiagnosisCode(item, code) {
item.DiagnosisCodes.remove(code);
}
function submitJSON() {
var test= ko.mapping.toJSON(viewModel); // have also tried ko.toJSON(viewModel)
alert(test);
}
var vm = {
"DiagnosisCodes": ["2345","6789"]
};
var viewModel = ko.mapping.fromJS(vm);
ko.applyBindings(viewModel);
</script>
So for example, if I click Add and type the code ABCD and then call submitJSON, I see :
{
DiagnosisCodes:["2345","6789",""]
}
I am expecting
{
DiagnosisCodes:["2345","6789","ABCD"]
}
UPDATE: it looks like the mapping plugin converts arrays of simple types (strings, ints, etc) into observables instead of observableArrays. So I modified (with pax's help) the javascript to convert the string arrays to arrays of objects holding the strings, before calling the mapping. Then when converting to JSON, converting them back:
<h3>Diagnosis Codes<input type="button" value="Add" data-bind="click:AddDiagnosisCode"/></h3>
<div data-bind="foreach:DiagnosisCodes">
<div><input type="text" data-bind="value:code"/><input type="button" value="Remove" data-bind="click: $root.RemoveDiagnosisCode"/>
</div>
</div>
<button onclick="submitJSON()">Show</button>
function submitJSON() {
//convert to JS object first
var test= ko.mapping.toJS(viewModel);
UnMapCodes(test);
alert(ko.toJSON(test));
}
function Code(code)
{
var self=this;
self.code = code;
}
function MapToCodes(obj)
{
var codes=[];
for(var c=0; c<obj.DiagnosisCodes.length; c++)
{
codes.push(new Code(obj.DiagnosisCodes[c]));
}
obj.DiagnosisCodes=codes;
}
function UnMapCodes(obj)
{
var codes=[];
for(var c=0; c<obj.DiagnosisCodes.length; c++)
{
codes.push(obj.DiagnosisCodes[c].code);
}
obj.DiagnosisCodes=codes;
}
var vm = {
"DiagnosisCodes": ["2345","6789"]
};
vm.AddDiagnosisCode= function (item)
{
self=this;
self.DiagnosisCodes.push(new Code(""));
};
vm.RemoveDiagnosisCode= function (code) {
self=this;
self.DiagnosisCodes.remove(code);
};
MapToCodes(vm);
var viewModel = ko.mapping.fromJS(vm);
ko.applyBindings(viewModel);
Upvotes: 0
Views: 157
Reputation: 4735
There were several problems with the code, restructured it a bit (fiddle: http://jsfiddle.net/VX9f2/2/):
html:
<button data-bind="click:submitJSON">submit json</button>
<h3>Diagnosis Codes<input type="button" value="Add" data-bind="click:AddDiagnosisCode"/></h3>
<div data-bind="foreach:DiagnosisCodes">
<div><input type="text" data-bind="value:code"/><input type="button" value="Remove" data-bind="click: $root.RemoveDiagnosisCode"/>
</div>
</div>
js:
var Code = function(code){
var self = this;
self.code = ko.observable(code);
}
var VM = function(){
var self = this;
self.DiagnosisCodes = ko.observableArray([
new Code("2345"),
new Code("6789")]);
self.AddDiagnosisCode = function() {
self.DiagnosisCodes.push(new Code(""));
}
self.RemoveDiagnosisCode = function(item) {
self.DiagnosisCodes.remove(item);
}
self.submitJSON = function() {
var test= ko.mapping.toJSON(self.DiagnosisCodes); // have also tried ko.toJSON(viewModel)
alert(test);
}
}
//var viewModel = ko.mapping.fromJS(new VM());
ko.applyBindings(new VM());
For clarity, I replaced the initial ko.mapping usage with constructors. It you still wish to use it, let me know.
Upvotes: 2