DIG*_*IDY 7 knockout-mapping-plugin knockout-2.0 knockout-mvc typescript
让我们先提前感谢:)
好的,所以我试图使用knockout.mapping插件从匹配的JSON数据加载/映射分层的TypeScript/KnockoutJS类型的类,层次结构可以是N度.
我知道我可以执行以下操作来从JSON数据映射/加载顶级类.
var qry = ko.mapping.fromJS(jsData, {}, new Query());
Run Code Online (Sandbox Code Playgroud)
但是我无法弄清楚如何将复杂的,N度,分层JSON数据映射/加载到一组TypeScript/KnockoutJS类并构建父/子关系.
我读过无数的艺术品,但是除了简单的父/子示例之外,它们在层次关系方面都不尽如人意,而且我无法使用knockout.mapping插件找到它们.
以下是我希望映射/加载的TypeScript类的减少定义.我是一个c ++/c#开发人员,所以这种性质的JavaScript对我来说是一个新手.
TypeScript对象
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>();
}
}
}
Run Code Online (Sandbox Code Playgroud)
JSON看起来像这样:
{
"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": []
}
]
}
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,经过大量的头发拉动和数字测试后,我现在更进一步了.
下面是我正在尝试实现的几乎可行的示例,唯一的问题是它似乎没有正确映射,即使单步执行代码似乎表明它正确加载.只有当我将它与我的绑定一起使用时,它才会在RootTaget.Filter.Type上抛出一个null未引用的绑定,该绑定应该填充一个值.
我仍在试图找出原因,但我会欢迎有关可能出现的错误的建议.:)
现在固定和工作
半工作打字稿
///<reference path="Scripts/typings/jquery/jquery.d.ts"/>
///<reference path="Scripts/typings/knockout/knockout.d.ts"/>
///<reference path="Scripts/typings/knockout.mapping/knockout.mapping.d.ts"/>
module ViewModel
{
export class Query {
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public RootTargetID: KnockoutObservable<number>;
public RootTarget: KnockoutObservable<QueryTarget>;
constructor(json: any) {
this.ID = ko.observable<number>(0);
this.Name = ko.observable<string>();
this.RootTargetID = ko.observable<number>();
this.RootTarget = ko.observable<QueryTarget>();
var mapping = {
'RootTarget': {
create: function (args) {
return new QueryTarget(args.data, null);
}
}
};
ko.mapping.fromJS(json, mapping, this);
}
}
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(json: any, parent: QueryTarget) {
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>(parent);
this.Selects = ko.observableArray<QuerySelect>();
this.FilterID = ko.observable<number>(0);
this.Filter = ko.observable<FilterClause>();
var mapping = {
'Children': {
create: function (args) {
return new QueryTarget(args.data, this);
}
},
'Selects': {
create: function (args) {
return new QuerySelect(args.data, this);
}
},
'Filter': {
create: function (args) {
return new FilterClause(args.data, null);
}
}
};
ko.mapping.fromJS(json, mapping, this);
}
}
export class QuerySelect {
public ID: KnockoutObservable<number>;
public Name: KnockoutObservable<string>;
public Aggregation: KnockoutObservable<string>;
public TargetID: KnockoutObservable<number>;
public Target: KnockoutObservable<QueryTarget>;
constructor(json: any, parent: QueryTarget) {
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>(parent);
ko.mapping.fromJS(json, {}, this);
}
}
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>;
constructor(json: any, parent: FilterClause) {
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>(parent);
this.Children = ko.observableArray<FilterClause>();
var mapping = {
'Children': {
create: function (args) {
return new FilterClause(args.data, this);
}
}
};
ko.mapping.fromJS(json, mapping, this);
}
}
export class QueryModuleViewModel
{
public QueryObj: Query;
constructor() {
var json = {
"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": []
}
]
}
}
}
//$.getJSON("/api/query/2", null,
// d => {
// this.QueryObj = new Query(d);
// })
this.QueryObj = new Query(json);
}
}
}
window.onload = () => {
ko.applyBindings(new ViewModel.QueryModuleViewModel());
};
Run Code Online (Sandbox Code Playgroud)
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="query.js"></script>
<!--<script src="my_js_query_test_all.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 and Filter data</p>
<p>RootTarget.ID: <input data-bind="value: RootTarget().ID" /></p>
<p>RootTarget.Name: <input data-bind="value: RootTarget().Name" /></p>
<p>TYPE: <input data-bind="value: RootTarget().Filter().Type" /></p>
<hr />
<p>RootTarget.FilterClause Hierarcy</p>
<div data-bind="with: RootTarget().Filter">
<div data-bind="template: { name: 'QueryListClauseTemplate' }"></div>
</div>
<hr />
<p>RootTarget.Selects</p>
<div data-bind="foreach: { data: RootTarget().Selects }">
<div data-bind="template: { name: 'QueryListSelectsTemplate' }"></div>
</div>
</div>
<script type="text/template" id="QueryListClauseTemplate">
<a title="FilterClause.Type" href="#" data-bind="text: Type" />
<div data-bind="foreach: { data: Children }">
<div data-bind="template: { name: 'QueryListClauseTemplate' }"></div>
</div>
</script>
<script type="text/template" id="QueryListSelectsTemplate">
<a title="Select.Name" href="#" data-bind="text: Name" />
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4049 次 |
| 最近记录: |