2

ノックアウト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);
});

問題は、ソースデータが変更され、テンプレートが新しいデータに再バインドされると、次のエラーがスローされることです。

キャッチされないエラー:バインディングを解析できません。メッセージ:ReferenceError:テキストが定義されていません。バインディング値:attr:{タイトル:テキスト}

ko.cleanNode(element)ノックアウトのバインディングを削除するために使用することを提案する別の投稿を見つけましたが、これは私の場合の問題を解決していません。

再バインド時にこのエラーを防ぐために、複製された要素のノックアウトのバインドを削除する方法はありますか?そうでない場合は、クリックした要素から必要なデータを抽出して、要素を「手動で」複製します。

これが私がしていることの簡単な例です

4

2 に答える 2

3

data-bindDOMをトラバースし、属性とノックアウトコメントを削除することで、要素からすべてのノックアウトバインディングを削除できます。

を使用します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);
        }
    }
}
于 2013-02-27T10:14:57.747 に答える
0

オリバー、jQueryを使用して、このようにノックアウトにバインドされた要素のクローンを作成することはお勧めできません。にはデータバインディングを使用する必要がありますtargetNode。まだ行っていない場合は、ノックアウトチュートリアルを実行して、基本的な使用法を十分に理解することをお勧めします。

クローンボタンを使用してアイテムのリストを保持しようとしている場合は、ノックアウトだけを使用して、これが非常に単純なフィドルです。あなたが何か他のことをしようとしているなら、私に知らせてください。あなたの質問はあなたの目標について完全に明確ではありません。

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));
    };
};
于 2013-02-25T23:25:12.390 に答える