52

如何使剔除数据绑定对动态生成的元素起作用?例如,我在 div 中插入了一个简单的 html 选择菜单,并希望使用敲除选项绑定来填充选项。这就是我的代码的样子:

$('#menu').html('<select name="list" data-bind="options: listItems"></select>');

但这种方法不起作用。有任何想法吗?

4

8 回答 8

33

如果在绑定视图模型后动态添加此元素,它将不在视图模型中并且不会更新。你可以做两件事之一。

  1. 将元素添加到 DOM 并通过再次调用重新绑定ko.applyBindings();
  2. 或者从头开始将列表添加到 DOM,并将视图模型中的选项集合留空。在您稍后将元素添加到选项中之前,Knockout 不会渲染它。
于 2012-06-16T21:46:36.017 回答
15

淘汰赛 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 元素。然后还会评估添加的子元素......即它们的数据绑定属性。

于 2015-07-14T09:13:28.660 回答
11

重写 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());
  }
};

于 2015-04-13T12:38:27.910 回答
4

编辑:这似乎从LosManos指出的 2.3 IIRC 版本开始不起作用

您可以使用 myViewModel[newObservable] = ko.observable('') 将另一个 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>

于 2013-04-16T18:10:20.910 回答
4

对于 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);
    }
};
于 2016-02-26T14:52:23.693 回答
2

这是一个老问题,但这是我希望得到的最新答案(淘汰赛 3.3.0):

当使用 knockout 模板或自定义组件向预绑定的 observable 集合添加元素时,knockout 将自动绑定所有内容。您的示例看起来像一个可观察的菜单项集合可以完成开箱即用的工作。

于 2015-04-27T18:41:11.193 回答
1

基于这个现有的答案,我已经实现了与您最初的意图类似的东西:

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(). 如果您需要保留新元素并使其随着视图模型的变化而变化,请将 observable 传递给方法的viewModel参数extendBinding

于 2014-11-07T20:14:14.997 回答
0

查看此答案:如何使用预定义的文本和值选项定义自定义剔除“选项绑定”

ko.applyBindingsToNode特别有用。

于 2017-11-15T12:44:12.230 回答