これは何? †
- 不定個のラジオボタンを表示する
<input type="radio" name="person" data-bind="attr: {value: $data[0].value}, checked: $parent.selected"/>
- 要点
- value は attr: {value: $data.{element} } でバインディングする。$data は繰り返し中の要素
- チェック状態は $parent.selected でバインディングする。$parent は繰り返しの外。つまりルートの View Model を指す
- 2列に表示する
<tbody data-bind="foreach: people">
<!-- foreach 節の中では this = $data は people。view-model は $parent -->
<tr>
<td>
<label>
<input type="radio" name="person" data-bind="attr: {value: $data[0].value}, checked: $parent.selected"/>
<span data-bind="text: $data[0].label"></span>
</label>
</td>
<td>
<!-- ko if: $data.length > 1 -->
<label>
<input type="radio" name="person" data-bind="attr: {value: $data[1].value}, checked: $parent.selected"/>
<span data-bind="text: $data[1].label"></span>
</label>
<!-- /ko -->
</td>
</tr>
</tbody>
- 要点
- 要素が奇数個で、右側に表示するものがなければ表示しない
- knockout.js は、テキストを作り出すのではなく DOM を操作している。つまり、if の中がひとまとまりの DOM として成り立たない書き方はできない。こういうふうに、出てきた要素の偶奇によって開始タグ・終了タグだけを出力するような if 文は書けない
<tbody data-bind="foreach: people">
<!-- foreach 節の中では this = $data は people。view-model は $parent -->
<!-- ko if: $index % 2 == 0 -->
<!-- 偶数個目の要素で tr タグを開始する (これは動かない) -->
<tr>
<!-- /ko -->
<td>
<label>
<input type="radio" name="person" data-bind="attr: {value: $data.value}, checked: $parent.selected"/>
<span data-bind="text: $data.label"></span>
</label>
</td>
<!-- ko if: $index % 2 == 1 -->
<!-- 奇数個目の要素で tr タグを閉じる (これは動かない) -->
</tr>
<!-- /ko -->
</tbody>
- 面倒でも、一列分のデータを配列にする必要がある
サンプルアプリケーション †
ソースコード †
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>knockdown.js ExD</title>
<style>
</style>
<script type="text/javascript" charset="UTF-8" src="js/lib/require.js" data-main="js/knockoutExD_init.js"></script>
</head>
<body>
<table>
<thead>
<tr>
<th>left</th>
<th>right</th>
</tr>
</thead>
<tbody data-bind="foreach: people">
<!-- foreach 節の中では this = $data は people。view-model は $parent -->
<tr>
<td>
<label>
<input type="radio" name="person" data-bind="attr: {value: $data[0].value}, checked: $parent.selected"/>
<span data-bind="text: $data[0].label"></span>
</label>
</td>
<td>
<!-- ko if: $data.length > 1 -->
<label>
<input type="radio" name="person" data-bind="attr: {value: $data[1].value}, checked: $parent.selected"/>
<span data-bind="text: $data[1].label"></span>
</label>
<!-- /ko -->
</td>
</tr>
</tbody>
</table>
You selected <span data-bind="text: selected"></span>.
</body>
</html>
/*
* アプリケーションのイニシャライザ.
*/
require.config({
// Javascript の Base Url
baseUrl: 'js/lib',
// ライブラリのパスの別名を定義する
paths: {
'app': '../',
'knockout' : 'knockout-3.2.0',
},
// AMDに対応してないモジュールを読み込む
shim: {
}
});
require(['knockout', 'app/knockoutExD_vmodel', 'domReady!'],
function(ko, vmdl) {
ko.applyBindings(new vmdl());
}
);
/*
* アプリケーションの View Model.
*/
define(['knockout'], function(ko) {
return function appViewModel() {
var self = this;
self.people = new ko.observableArray([
[{ value: 'b', label: 'Bertington' },{ value: 'd', label: 'Dentiste' }],
[{ value: 'c', label: 'Charlesforth' },{ value: 'a', label: 'Angela' }],
[{ value: 'z', label: 'Zara'}]
]);
console.log(self.people());
self.selected = new ko.observable(self.people()[0][0].value.toString());
};
});
HTML