動的に生成された要素でノックアウトデータバインドを機能させるにはどうすればよいですか?たとえば、div内に単純なhtml選択メニューを挿入し、ノックアウトオプションバインディングを使用してオプションを設定したいとします。これは私のコードがどのように見えるかです:
$('#menu').html('<select name="list" data-bind="options: listItems"></select>');
しかし、この方法は機能しません。何か案は?
動的に生成された要素でノックアウトデータバインドを機能させるにはどうすればよいですか?たとえば、div内に単純なhtml選択メニューを挿入し、ノックアウトオプションバインディングを使用してオプションを設定したいとします。これは私のコードがどのように見えるかです:
$('#menu').html('<select name="list" data-bind="options: listItems"></select>');
しかし、この方法は機能しません。何か案は?
ビューモデルをバインドした後でこの要素をオンザフライで追加すると、ビューモデルに含まれず、更新されません。あなたは2つのことのうちの1つをすることができます。
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());
}
};
編集: 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>
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);
}
};
これは古い質問ですが、これが私の最新の回答(ノックアウト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
パラメーターにobservableを渡します。extendBinding
この回答を確認してください:事前定義されたテキストと値のオプションを使用して、カスタムノックアウトの「オプションバインディング」を定義するにはどうすればよいですか
ko.applyBindingsToNode
特に便利です。