Let's start with a thanks in advance :)
OK, So I'm trying to load/map hierarchical TypeScript/KnockoutJS typed classes from matching JSON data using the knockout.mapping plugin, the hierarchy can be to the Nth degree.
I know I can do the following to map/load the top level class from the JSON data.
var qry = ko.mapping.fromJS(jsData, {}, new Query());
However I can't figure out is how to map/load complex, Nth degree, hierarchical JSON data to a set of TypeScript/KnockoutJS classes and build the parent/child relationship.
I've read countless articals, but they all fall short when it comes to hierarchical relationships beyond simple parent/child examples, and I can find none using the knockout.mapping plugin.
Here are my cut down definitions of TypeScript classes I wish to map/load. I'm a c++/c# developer, so JavaScript of this nature is very new to me.
TypeScript Objects
module ViewModel
{
export class QueryModuleViewModel {
public QueryObj: KnockoutObservable<Query>;
constructor() {
this.QueryObj = ko.observable<Query>();
}
public Initialize() {
$.getJSON("/api/query/2", null,
d => {
var qry = ko.mapping.fromJS(d, {}, new Query());
this.QueryObj(qry);
});
}
}
export class Query
{
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public RootTargetID: KnockoutObservable<number>;
public RootTarget: KnockoutObservable<QueryTarget>;
constructor()
{
this.ID = ko.observable<number>(0);
this.Name = ko.observable<string>();
this.RootTargetID = ko.observable<number>();
this.RootTarget = ko.observable<QueryTarget>();
}
}
export class QueryTarget
{
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public ParentID: KnockoutObservable<number>;
public Children: KnockoutObservableArray<QueryTarget>;
public Parent: KnockoutObservable<QueryTarget>;
public Selects: KnockoutObservableArray<QuerySelect>;
public FilterID: KnockoutObservable<number>;
public Filter: KnockoutObservable<FilterClause>;
constructor()
{
this.ID = ko.observable<number>(0);
this.Name = ko.observable<string>();
this.ParentID = ko.observable<number>(0);
this.Children = ko.observableArray<QueryTarget>();
this.Parent = ko.observable<QueryTarget>();
this.Selects = ko.observableArray<QuerySelect>();
this.FilterID = ko.observable<number>(0);
this.Filter = ko.observable<FilterClause>();
}
}
export class QuerySelect
{
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public Aggregation: KnockoutObservable<string>;
public TargetID: KnockoutObservable<number>;
public Target: KnockoutObservable<QueryTarget>;
constructor()
{
this.ID = ko.observable<number>();
this.Name = ko.observable<string>();
this.Aggregation = ko.observable<string>();
this.TargetID = ko.observable<number>();
this.Target = ko.observable<QueryTarget>();
}
}
export class FilterClause
{
public FilterClauseID: KnockoutObservable<number>;
public Type: KnockoutObservable<string>;
public Left: KnockoutObservable<string>;
public Right: KnockoutObservable<string>;
public ParentID: KnockoutObservable<number>;
public Parent: KnockoutObservable<FilterClause>;
public Children: KnockoutObservableArray<FilterClause>;
public QueryTargets: KnockoutObservableArray<QueryTarget>;
constructor()
{
this.FilterClauseID = ko.observable<number>();
this.Type = ko.observable<string>();
this.Left = ko.observable<string>();
this.Right = ko.observable<string>();
this.ParentID = ko.observable<number>();
this.Parent = ko.observable<FilterClause>();
this.Children = ko.observableArray<FilterClause>();
}
}
}
The JSON would look something like this:
{
"ID": 2,
"Name": "Northwind 2",
"RootTargetID": 2,
"RootTarget": {
"ID": 2,
"Name": "Customers",
"ParentID": null,
"FilterID": 2,
"Queries": [],
"Children": [],
"Parent": null,
"Selects": [
{
"ID": 3,
"Name": "CompanyName",
"Aggregation": "None",
"TargetID": 2,
"Target": null
},
{
"ID": 4,
"Name": "ContactName",
"Aggregation": "None",
"TargetID": 2,
"Target": null
}
],
"Filter": {
"FilterClauseID": 2,
"Type": "AND",
"Left": null,
"Right": null,
"ParentID": null,
"QueryTargets": [],
"Parent": null,
"Children": [
{
"FilterClauseID": 3,
"Type": "NE",
"Left": "Country",
"Right": "Germany",
"ParentID": 2,
"QueryTargets": [],
"Parent": null,
"Children": []
},
{
"FilterClauseID": 4,
"Type": "NE",
"Left": "Country",
"Right": "Mexico",
"ParentID": 2,
"QueryTargets": [],
"Parent": null,
"Children": []
}
]
}
}
}