カスタム バインディングでは、次のことを行う必要があります。
- リスト内の各項目の要素を作成します
- その要素を親に追加します
- 元のビュー モデルで selectedItem を設定する各要素にクリック ハンドラーを追加します。
また、わかりやすくするために、現在選択されているアイテムを強調表示しました。
ko.bindingHandlers.myListView = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
//get the list of items
items = value.items(),
//get a reference to the selected item observable
selectedItem = value.selectedItem,
//get a jQuery reference to the element
$element = $(element),
//get the currently selected item
currentSelected = selectedItem();
//clear the parent of any existing children
$element.html("");
for (var index = 0; index < items.length; index++) {
(function() {
//get the list of items
var item = ko.utils.unwrapObservable(items[index]),
//create a child element with a click handler
$childElement = $("<li>")
.text(item.id() + " " + item.text())
.click(function() {
//remove selected class on all siblings
$(this).siblings().removeClass("selected");
//add selected class on this item
$(this).addClass("selected");
//set the observable 'selected item' property on the source view model
selectedItem(item);
});
//add the selected class if this item is the current selected item
if (item == currentSelected) {
$childElement.addClass("selected");
}
//add the child to the parent
$element.append($childElement);
})();
}
}
};
これが実際の例です
注:メソッドのupdate
代わりにを使用しているinit
ため、コメントのリストを更新するときに機能します
アップデート
元の DIV の内容を、作成された各項目のテンプレートとして使用する場合は、さらに 2 つの手順が必要です。
- 初期化時に要素の元のコンテンツを取得し、上記のハードコードされたコンテンツの代わりにそれを使用します
DOM に追加する前に、作成した要素にバインディングを適用する
ko.bindingHandlers.myListView = {
init: function(element) {
var $element = $(element),
originalContent = $element.html();
$element.data("original-content", originalContent);
return { controlsDescendantBindings: true }
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
//get the list of items
items = value.items(),
//get a reference to the selected item observable
selectedItem = value.selectedItem,
//get a jQuery reference to the element
$element = $(element),
//get the currently selected item
currentSelected = selectedItem(),
//get the current content of the element
elementContent = $element.data("original-content");
$element.html("");
for (var index = 0; index < items.length; index++) {
(function() {
//get the list of items
var item = ko.utils.unwrapObservable(items[index]),
//create a child element with a click handler
$childElement = $(elementContent)
.click(function() {
//remove selected class on all siblings
$(this).siblings().removeClass("selected");
//add selected class on this item
$(this).addClass("selected");
//set the observable 'selected item' property on the source view model
selectedItem(item);
});
ko.applyBindings(item, $childElement[0]);
//add the selected class if this item is the current selected item
if (item == currentSelected) {
$childElement.addClass("selected");
}
//add the child to the parent
$element.append($childElement);
})();
}
}
};
{ controlsDescendantBindings: true }
メソッドから戻ることで、div のコンテンツがノックアウトによって処理されるのを防ぐ必要があることに注意してくださいinit
。
これが更新された例です