JSONオブジェクトには可変キーがあるため、最初に固定の予測可能な構造に変換する必要があります。そうしないと、ネストされたテンプレートマッピングが機能しません(ノックアウトは宣言型であるため、キー名を事前に知っておく必要があります)。
次のカスタムマッピングコードを検討してください(ノックアウトマッピングプラグインは必要ありません)。
var ListModel = function(jsonData) {
var self = this;
self.master = ko.observableArray([]);
function nestedMapping(data, level) {
var key, value, type;
for (key in data) {
if (data.hasOwnProperty(key)) {
if (data[key] instanceof Object) {
type = "array";
value = ko.observableArray([]);
nestedMapping(data[key], value());
} else {
type = "simple";
value = ko.observable(data[key]);
}
level.push({key: key, type: type, value: value});
}
}
}
nestedMapping(jsonData, self.master());
}
この関数nestedMapping()
はデータ構造を変えます:
{
"Level 1a": "Hi",
"Level 1b": {
"Level 2a": "Hello",
"Level 2b": {
"Level 3": "Bye"
}
}
}
の中へ:
[
{
"key": "Level 1a",
"type": "simple",
"value": "Hi"
},
{
"key": "Level 1b",
"type": "array",
"value": [
{
"key": "Level 2a",
"type": "simple",
"value": "Hello"
},
{
"key": "Level 2b",
"type": "array",
"value": [
{
"key": "Level 3",
"type": "simple",
"value": "Bye"
}
]
}
]
}
]
これで、次のようなテンプレートを作成できます。
<script type="text/html" id="nestedTemplate">
<!-- ko if: type == 'simple' -->
<div class="name" data-bind="text: value, attr: {title: key}"></div>
<!-- /ko -->
<!-- ko if: type == 'array' -->
<div class="container" data-bind="
template: {
name: 'nestedTemplate',
foreach: value
}
"></div>
<!-- /ko -->
</script>
それが機能していることを確認してください:http://jsfiddle.net/nwdhJ/2/
についての微妙ですが重要な点に注意してくださいnestedMapping()
。ネストされたobservables/observableArraysを作成します。ただし、ネイティブ配列インスタンスで機能します(再帰に渡すことによって)self.master()
。value()
このようにして、オブジェクト構築中の不必要な遅延を回避します。observableArrayに値をプッシュするたびに、ノックアウト変更の追跡がトリガーされますが、それは必要ありません。ネイティブアレイでの作業はかなり高速になります。