I'm trying to map JSON data using the knockout.mapping plugin, however the heirarcical JSON data fails to populate my object properties correctly, the top level loads fine but not the child 'RootTarget' data?
What am I doing wrong?
Knockout Javascript
var Query = function(json)
{
this.ID = ko.observable(0);
this.Name = ko.observable();
this.RootTargetID = ko.observable();
this.RootTarget = ko.observable();
var mapping = {
'RootTarget': {
create: function (args) {
return new QueryTarget(args.data, null);
}
}
};
ko.mapping.fromJS(json, mapping, this);
}
var QueryTarget = function(json, parent)
{
this.ID = ko.observable(0);
this.Name = ko.observable();
this.ParentID = ko.observable(0);
this.Parent = ko.observable(parent);
this.FilterID = ko.observable(0);
var mapping = {
'ignore': ["Parent"]
};
ko.mapping.fromJS(json, mapping, this);
}
var QueryModuleViewModel = function()
{
var json = {
"ID": 2,
"Name": "Northwind 2",
"RootTargetID": 2,
"RootTarget": {
"ID": 2,
"Name": "Customers",
"ParentID": null,
"FilterID": 2,
"Parent": null
}
};
this.QueryObj = new Query(json);
}
window.onload = function () {
ko.applyBindings(new QueryModuleViewModel());
};
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>TypeScript Knockout Mapping Query Test</title>
<link rel="stylesheet" href="app.css" type="text/css" />
<script src="Scripts/jquery-2.0.2.js" type="text/javascript"></script>
<script src="Scripts/knockout-2.2.1.debug.js" type="text/javascript"></script>
<script src="Scripts/knockout.mapping-latest.debug.js" type="text/javascript"></script>
<script src="my_js_query_test.js"></script>
</head>
<body>
<h1>TypeScript Knockout Mapping Query Test</h1>
<div data-bind="with: QueryObj">
<span data-bind="blah: console.log($context)"></span>
<p>Query Name: <input data-bind="value: Name" /></p>
<hr />
<p>Quick test of RootTarget Values</p>
<p>RootTarget.ID: <input data-bind="value: RootTarget.ID" /></p>
<p>RootTarget.Name: <input data-bind="value: RootTarget.Name" /></p>
</div>
</body>
</html>
Because your
RootTarget
is declared as anko.observable
which is a function so you need to call it with empty args()
to get its value and access the stored object.So you just need to change your bindings and add the missing
()
:Demo JSFiddle.
Or you can use here the
with
bindingDemo JSFiddle.
It has some nice advantages:
RootTarget
with
automatically unwraps the observables so you can just writewith: RootTarget
, no parens neededRootTarget
value isnull
orundified
so it hides the inputs while your original solutionRootTarget().ID
would throw a null reference exception.You need brackets on your roottarget mappings as you need to evaluate the observable before you can get it's properties.
Alternatively, RootTarget doesn't actually need to be an observable, only its properties do, so if you remove the line below it'll automatically be created as a normal object and your bindings will work as they are.