動的に生成された要素でノックアウトデータバインドを機能させるにはどうすればよいですか?たとえば、単純なhtml選択メニューをdiv内に挿入し、ノックアウトオプションバインディングを使用してオプションを設定します。これは私のコードのようです:
$('#menu').html('<select name="list" data-bind="options: listItems"></select>');
しかし、この方法は機能しません。何か案は?
ビューモデルをバインドした後にこの要素をオンザフライで追加すると、ビューモデルには含まれなくなり、更新されません。次の2つのいずれかを実行できます。
ko.applyBindings();
を再度呼び出して再バインドしますノックアウト3.3
ko.bindingHandlers.htmlWithBinding = {
'init': function() {
return { 'controlsDescendantBindings': true };
},
'update': function (element, valueAccessor, allBindings, viewModel, bindingContext) {
element.innerHTML = valueAccessor();
ko.applyBindingsToDescendants(bindingContext, element);
}
};
上記のコードスニペットでは、「htmlWithBinding」プロパティを使用してHTML要素を動的に挿入できます。追加された子要素も評価されます...つまり、データバインド属性です。
htmlバインディングコードを書き換えるか、新しいものを作成します。 htmlバインディングは、動的htmlで「注入されたバインディング」を防ぐため:
ko.bindingHandlers['html'] = {
//'init': function() {
// return { 'controlsDescendantBindings': true }; // this line prevents parse "injected binding"
//},
'update': function (element, valueAccessor) {
// setHtml will unwrap the value if needed
ko.utils.setHtml(element, valueAccessor());
}
};
V3.4.0の場合、以下のカスタムバインディングを使用します。
ko.bindingHandlers['dynamicHtml'] = {
'update': function (element, valueAccessor, allBindings, viewModel, bindingContext) {
// setHtml will unwrap the value if needed
ko.utils.setHtml(element, valueAccessor());
ko.applyBindingsToDescendants(bindingContext, element);
}
};
編集: LosManosが指すバージョン2.3 IIRC以降では機能しないようです
MyViewModel [newObservable] = ko.observable( '')を使用して、ビューモデルに別のオブザーバブルを追加できます。
その後、再びko.applyBindingsを呼び出します。
これは、段落を動的に追加し、新しいビューモデルとバインディングが問題なく機能するシンプルなページです。
// myViewModel starts only with one observable
var myViewModel = {
paragraph0: ko.observable('First')
};
var count = 0;
$(document).ready(function() {
ko.applyBindings(myViewModel);
$('#add').click(function() {
// Add a new paragraph and make the binding
addParagraph();
// Re-apply!
ko.applyBindings(myViewModel);
return false;
});
});
function addParagraph() {
count++;
var newObservableName = 'paragraph' + count;
$('<p data-bind="text: ' + newObservableName + '"></p>').appendTo('#placeholder');
// Here is where the magic happens
myViewModel[newObservableName] = ko.observable('');
myViewModel[newObservableName](Math.random());
// You can also test it in the console typing
// myViewModel.paragraphXXX('a random text')
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<div id="placeholder">
<p data-bind="text: paragraph0"></p>
</div>
<a id="add" href="#">Add paragraph</a>
それは古い質問ですが、うまくいけば私の最新の答えです(knockout 3.3.0):
ノックアウトテンプレートまたはカスタムコンポーネントを使用して、事前バインドされたオブザーバブルコレクションに要素を追加すると、ノックアウトはすべてを自動的にバインドします。あなたの例は、メニュー項目の観察可能なコレクションが箱から出して仕事をするように見えます。
この既存の答え に基づいて、私はあなたの最初の意図に似た何かを達成しました:
_function extendBinding(ko, container, viewModel) {
ko.applyBindings(viewModel, container.children()[container.children().length - 1]);
}
function yourBindingFunction() {
var container = $("#menu");
var inner = $("<select name='list' data-bind='options: listItems'></select>");
container.empty().append(inner);
extendBinding(ko, container, {
listItems: ["item1", "item2", "item3"]
});
}
_
ここに JSFiddle があります。
新しい要素がdomの一部になったら、_ko.applyBindings
_-を呼び出して再バインドすることはできませんので、container.empty()
を使用しています。新しい要素を保持し、ビューモデルの変更に合わせて変更する必要がある場合は、viewModel
メソッドのextendBinding
パラメーターにオブザーバブルを渡します。
この回答を確認してください: 定義済みのテキストおよび値オプションでカスタムノックアウト「オプションバインディング」を定義する方法
ko.applyBindingsToNode
は特に便利です。