2012-06-16 71 views
40

基於動態生成元素的基因敲除數據綁定工作如何實現?例如,我在div中插入一個簡單的html選擇菜單,並希望使用knockout選項綁定來填充選項。這是我的代碼的樣子:基於動態生成元素的基因敲除數據綁定

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

但這種方法不起作用。有任何想法嗎?

+0

你是否在你完成你的ko.applyBindings(yourVMHere)後添加這個; – PlTaylor

+0

在這個動態添加的DOM元素上放下(自動)KO綁定的想法並手動處理。 – Vaibhav

回答

30

如果您在綁定viewmodel後即時添加此元素,它將不會在viewmodel中並且不會更新。你可以做兩件事之一。

  1. 的元素添加到DOM,並再次調用ko.applyBindings();
  2. 重新綁定,或列表中從一開始就加入到DOM並保留選項收集您的視圖模型空。敲擊將不會渲染它,直到您稍後將元素添加到選項中。
+11

如果我再次調用applyBindings,它會拋出一個錯誤:錯誤:您無法多次將綁定應用於同一元素。 – Chris

+2

這必須是更新框架的新特性。第二種選擇仍然是可行的,說實話,這是更好的選擇。 – PlTaylor

+1

是的,我認爲,在一個元素上多次應用綁定是不好的做法。因爲它會觸發2次,所以我認爲這就是爲什麼他們在KO 3中添加了一些警告。 – Chris

3

編輯:看來,這並不因爲版本2.3 IIRC工作由LosManos

的指出你可以使用另一個可觀測添加到您的視圖模型myViewModel [newObservable] = ko.observable(」 ')

之後,再次調用ko.applyBindings。

這是一個簡單的頁面,我可以動態添加段落,並且新的視圖模型和綁定完美地工作。

// myViewModel starts only with one observable 
 
    \t var myViewModel = { 
 
    \t  paragraph0: ko.observable('First') 
 
    \t }; 
 
    
 
    \t var count = 0; 
 
    
 
    \t $(document).ready(function() { 
 
    \t \t ko.applyBindings(myViewModel); 
 
    
 
    \t \t $('#add').click(function() { 
 
    \t \t \t // Add a new paragraph and make the binding 
 
    \t \t \t addParagraph(); 
 
    \t \t \t // Re-apply! 
 
    \t \t \t ko.applyBindings(myViewModel); \t \t \t 
 
    \t \t \t return false; \t 
 
    \t \t }); 
 
    \t }); 
 
    
 
    \t function addParagraph() { 
 
    \t \t count++; 
 
    \t \t var newObservableName = 'paragraph' + count; 
 
    \t  $('<p data-bind="text: ' + newObservableName + '"></p>').appendTo('#placeholder'); 
 
    \t \t 
 
    \t  // Here is where the magic happens 
 
    \t \t myViewModel[newObservableName] = ko.observable(''); 
 
    \t \t myViewModel[newObservableName](Math.random()); 
 
    
 
    \t \t // You can also test it in the console typing 
 
    \t \t // myViewModel.paragraphXXX('a random text') 
 
    \t }
<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>

+7

多次調用applyBindings不是一個好主意。 – gliljas

+0

@ gunteman ..爲什麼不呢? – lamarant

+3

這似乎是拋出相同的「無法應用綁定兩次」的錯誤。是否有可能告訴ko.applyBindings()你想添加到綁定的非常特定的元素? – Chris

0

基於this existing answer,我achived類似的東西到你的初始意圖:

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()的原因。如果您需要保留新元素並在視圖模型更改時將其更改,請將可觀察值傳遞給extendBinding方法的viewModel參數。

10

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

+3

在查看關於此線程的所有答案和評論之後,IMO實際上是「敲除動態生成的元素上的數據綁定」問題的最佳解決方案。好解決方案! – MattSizzle

1

這是一個老問題,但這裏是我的希望了最新的答案(淘汰賽3.3.0):

在動態HTML,因爲HTML結合阻止「注入綁定」當使用挖空模板或自定義組件將元素添加到預先綁定的可觀察集合時,挖空將自動綁定所有內容。您的示例看起來像一個可觀察的菜單項集合,可以完成開箱即用的工作。

10

基因敲除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元素。然後也評估所添加的子元素,即其數據綁定屬性。

3

對於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); 
    } 
};