Javascript 动态生成元素上的敲除数据绑定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11066732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
knockout data-bind on dynamically generated elements
提问by King Julien
How is it possible to make knockout data-bind work on dynamically generated elements? For example, I insert a simple html select menu inside a div and want to populate options using the knockout options binding. This is what my code looks like:
如何在动态生成的元素上进行敲除数据绑定?例如,我在 div 中插入一个简单的 html 选择菜单,并希望使用淘汰赛选项绑定来填充选项。这是我的代码的样子:
$('#menu').html('<select name="list" data-bind="options: listItems"></select>');
but this method doesn't work. Any ideas?
但这种方法不起作用。有任何想法吗?
采纳答案by PlTaylor
If you add this element on the fly after you have bound your viewmodel it will not be in the viewmodel and won't update. You can do one of two things.
如果在绑定视图模型后即时添加此元素,它将不在视图模型中并且不会更新。你可以做两件事之一。
- Add the element to the DOM and re-bind it by calling
ko.applyBindings();
again - OR add the list to the DOM from the beginning and leave the options collection in your viewmodel empty. Knockout won't render it until you add elements to options on the fly later.
- 将元素添加到 DOM 并通过
ko.applyBindings();
再次调用重新绑定 - 或者从一开始就将列表添加到 DOM 并将视图模型中的选项集合留空。Knockout 不会渲染它,直到您稍后将元素添加到选项中。
回答by Stevanicus
Knockout 3.3
淘汰赛 3.3
ko.bindingHandlers.htmlWithBinding = {
'init': function() {
return { 'controlsDescendantBindings': true };
},
'update': function (element, valueAccessor, allBindings, viewModel, bindingContext) {
element.innerHTML = valueAccessor();
ko.applyBindingsToDescendants(bindingContext, element);
}
};
Above code snippet allows you to inject html elements dynamically with the "htmlWithBinding" property. The child elements which are added are then also evaluated... i.e. their data-bind attributes.
上面的代码片段允许您使用“htmlWithBinding”属性动态注入 html 元素。然后还评估添加的子元素……即它们的数据绑定属性。
回答by Salomón
rewrite html binding code or create a new. Because html binding prevents "injected bindings" in dynamical 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());
}
};
回答by vivanov
For v3.4.0 use the custom binding below:
对于 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);
}
};
回答by Ivan Malagon
EDIT: It seems that this doesn't work since version 2.3 IIRC as pointed by LosManos
编辑:从LosManos指出的 2.3 IIRC 版本以来,这似乎不起作用
You can add another observable to your view model using myViewModel[newObservable] = ko.observable('')
您可以使用 myViewModel[newObservable] = ko.observable('') 向您的视图模型添加另一个 observable
After that, call again to ko.applyBindings.
之后,再次调用 ko.applyBindings。
Here is a simple page where I add paragraphs dynamically and the new view model and the bindings work flawlessly.
这是一个简单的页面,我在其中动态添加段落,并且新的视图模型和绑定完美无缺。
// 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>
回答by johanneslink
It's an old question but here's my hopefully up-to-date answer (knockout 3.3.0):
这是一个老问题,但这是我希望最新的答案(淘汰赛 3.3.0):
When using knockout templates or custom components to add elements to prebound observable collections, knockout will bind everything automatically. Your example looks like an observable collection of menu items would do the job out of the box.
当使用 Knockout 模板或自定义组件将元素添加到预绑定的 observable 集合时,knockout 将自动绑定所有内容。您的示例看起来像一个可观察的菜单项集合可以开箱即用。
回答by Antoni
Checkout this answer: How do define a custom knockout 'options binding' with predefined Text and Value options
查看此答案:如何使用预定义的文本和值选项定义自定义淘汰赛“选项绑定”
ko.applyBindingsToNode
is particularly useful.
ko.applyBindingsToNode
特别有用。
回答by Ivaylo Slavov
Based on this existing answer, I've achived something similar to your initial intentions:
基于这个现有的答案,我已经实现了与您最初的意图类似的东西:
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"]
});
}
Here is a JSFiddleto play with.
这是一个可以玩的JSFiddle。
Be warned, once the new element is part of the dom, you cannot re-bind it with a call to ko.applyBindings
- that is why I use container.empty()
. If you need to preserve the new element and make it change as the view model changes, pass an observable to the viewModel
parameter of the extendBinding
method.
请注意,一旦新元素成为 dom 的一部分,就无法通过调用重新绑定它ko.applyBindings
- 这就是我使用container.empty()
. 如果您需要保留新元素并使其随着视图模型的更改而更改,请将 observable 传递给viewModel
该extendBinding
方法的参数。