2013-02-25 177 views
2

上綁定我現在用的是淘汰賽JS模板綁定功能,以使項目集合到一個元素:刪除淘汰賽JS克隆元素

<script type="text/javascript"> 
    ko.applyBindings(new function() { 
     this.childItems = [{ Text: "Test", ImageUrl: "Images/Image.png" }]; 
    }); 
</script> 

<script type="text/html" id="template"> 
    <div class="childItem" data-bind="attr: { title: Text }"> 
     <img data-bind="attr: { src: ImageUrl }" /> 
    </div> 
</script> 

<div class="childSelector" data-bind="template: { name: 'template', foreach: childItems }"> 
</div> 

點擊時,孩子的物品被克隆並放置到另一個元素:

$(".childSelector").on("click", ".childItem", function() { 
    var clone = $(this).clone()[0]; 
    ko.cleanNode(clone); 
    $(".targetNode").append(clone); 
}); 

的問題是,當源數據變化和模板重新綁定到新的數據,下面的錯誤被拋出:

Uncaught Error: Unable to parse bindings. Message: ReferenceError: Text is not defined; Bindings value: attr: { title: Text }

我發現了另一篇文章,建議使用ko.cleanNode(element)刪除淘汰賽的綁定,但是這並沒有解決我的問題。

有沒有辦法刪除克隆元素上的敲除綁定,以防止重新綁定時出現此錯誤?如果沒有,我只需通過從單擊元素中提取所需數據來「手動」克隆元素。

Here是我在做

回答

3

您可以通過遍歷DOM和移除data-bind屬性移除一個元素都淘汰賽綁定和基因敲除的意見。

使用removeDataBindings(clone);但首先用ko.cleanNode(clone)清理節點以清除任何事件處理程序。

var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->"; 
var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/; 
var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/; 

function isStartComment(node) { 
    return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex); 
} 

function isEndComment(node) { 
    return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex); 
} 

function traverseNode(node, func) { 
    func(node); 
    node = node.firstChild; 
    while (node) { 
     traverseNode(node, func); 
     node = node.nextSibling; 
    } 
} 

function removeDataBindings(element) { 
    var koComments = []; 

    traverseNode(element, function (node) { 
     if (isStartComment(node) || isEndComment(node)) { 
      koComments.push(node); 
      return; 
     } 
     //remove the 'data-bind' attributes 
     if (node.nodeType === 1) { //ELEMENT_NODE 
      node.removeAttribute('data-bind'); 
     } 
    }); 

    //remove Knockout binding comments 
    for (i = 0; i < koComments.length; i++) { 
     node = koComments[i]; 
     if (node.parentNode) { 
      node.parentNode.removeChild(node); 
     } 
    } 
} 
+0

感謝你們,我接受了建議,並沒有按照我原來的路線走,但是這爲未來的訪問者回答了問題! – Oliver 2013-02-27 17:11:40

0

什麼奧利弗,使用jQuery克隆綁定到淘汰賽單元這樣一個簡單的例子是不是一個好主意。你應該使用targetNode的數據綁定。如果您還沒有這樣做,最好通過Knockout Tutorials來了解基本用途。

如果您嘗試使用克隆按鈕來保留項目列表,這裏使用的是dead simple fiddle,但它只使用Knockout來執行此操作。如果你正在嘗試做其他事情,請告訴我。你的問題並不完全清楚你的目標。

HTML:

<div data-bind="foreach: items"> 
    <span data-bind="text: $data"></span> 
    <button data-bind="click: $parent.clone">Clone</button></br> 
</div> 

JS:

var ViewModel = function(data) { 
    var self = this; 
    self.items = ko.observableArray(data); 
    self.clone = function(item) { 
     //The ko.toJS here is a handy copy tool for viewModels 
     //It isn't necessary for simple arrays like this one 
     //But I included it because for an array of objects, you will want to use it 
     self.items.push(ko.toJS(item)); 
    }; 
}; 
+0

您好Tyrsius,請參閱我的問題的示例,在執行克隆後重新應用綁定時,會在控制檯中引發錯誤。這是我第一次使用淘汰賽,但是考慮一下,我可以將目標作爲可觀察數組而不是克隆源項目......你知道是否有關於刪除綁定的問題的答案? – Oliver 2013-02-25 23:45:16

+0

我看到錯誤,你讀了我的答案嗎?如果您正在使用Knockout,則不應將jQuery用於DOM克隆。該角色屬於Knockout。 – Tyrsius 2013-02-25 23:47:47

+0

我做過了,請參閱上面的評論,謝謝。 – Oliver 2013-02-25 23:49:18