0

Knockout.js を使用して、一連の HTML5<details>要素を設定しています。構造は次のとおりです。

<div class="items" data-bind="foreach: Playlists">
    <details class="playlist-details" data-bind="attr: {id: 'playlist-details-' + $index(), open: isOpen}">
        <summary>
            <span data-bind="text: name"></span> - <span data-bind="text: count"></span> item(s)
            <div class="pull-right">
                <button data-bind="click: $parent.play, css: {disabled: count() == 0}, attr: {title: playbtn_title}" class="btn"><i class="icon-play"></i> Play</button>
                <button data-bind="click: $parent.deleteList" class="btn btn-danger"><i class="icon-trash"></i> Delete</button>
            </div>
        </summary>
        <div class="list" data-bind="with: items" style="padding-top: 2px;">
            ...
        </div>
    </details>
</div>

ViewModel のデータは次のようになります。

var VM = {
    Playlists: [
        {
            name: "My Playlist1",
            count: 3,
            items: [<LIST OF SONG ID'S>],
            playbtn_title: "Play this playlist",
            isOpen: true
        },
        {
            name: "My Playlist2",
            count: 5,
            items: [<LIST OF SONG ID'S>],
            playbtn_title: "Play this playlist",
            isOpen: null
        },
        {
            name: "My Playlist3",
            count: 0,
            items: [],
            playbtn_title: "You need to add items to this list before you can play it!",
            isOpen: null
        }
    ]
};

ViewModel のプロパティとバインディングを使用して、詳細ビューの開いている状態または閉じている状態を記憶する機能を追加しました(最初に説明したように ここ)。isOpenattr

ただし、クリックし<summary>て詳細を展開しても、ViewModel は更新されません。バインディングとは異なりvalueattrバインディングは双方向ではありません。

属性値が変更されたときにこのバインディングを更新するにはどうすればよいですか?

要素が開いたり閉じたりしたときにブラウザがイベントをトリガーすることは知っていますが、DOMSubtreeModifiedそこに何を入れるかはわかりません-私が試したいくつかのこと(、、などを含む.notifySubscribers()if (list.open()) ...がループを引き起こし、プロパティが変更されるとイベント トリガーが再び発生すると、プロパティが再び変更され、イベントが再びトリガーされます。

4

2 に答える 2

0

最後に見つけた方法は、単にDOMSubtreeModified「手動で」値を更新することです。

$(document).on('DOMSubtreeModified', 'details.playlist-details', function(e) {
    var list = ko.dataFor(this);
    list.open(this.getAttribute('open'));
});

(どういうわけか、これは、私が試したより複雑な構造が引き起こしたループを引き起こしません。)

于 2014-07-16T16:56:36.267 に答える