2014-07-16 2 views
0

Knockout.js를 사용하여 HTML5 <details> 요소를 채우고 있습니다. 내가 뷰 모델의 isOpen 속성을 사용하고 세부 사항보기의 open or closed state을 기억 할 수있는 기능을 추가 한ViewModel 대신 DOM에서 knockout`attr` 바인딩을 업데이트하십시오.

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 
     } 
    ] 
}; 

: 뷰 모델에

<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> 

데이터는 다음과 같은 : 여기에 구조는 attr 결합 (원래는 here으로 기재 됨).

그러나 세부 사항을 확장하기 위해 <summary>을 클릭하면 value 바인딩과 달리 ViewModel이 업데이트되지 않습니다. attr 바인딩은 양방향이 아닙니다.

속성 값이 변경되면 어떻게이 바인딩을 업데이트 할 수 있습니까?

내가 브라우저가 요소 개폐되는 DOMSubtreeModified 이벤트를 트리거 것을 알고,하지만, 내가 거기에 넣어 될지 모르겠어요 - 원인 루핑 (등, .notifySubscribers(), if (list.open()) ... 포함) 내가 시도 몇 가지, 여기서 속성이 변경되면 이벤트가 다시 트리거되고 속성을 다시 변경하며 이벤트를 다시 트리거합니다.

답변

0

마지막으로 찾은 방법은 단순히 DOMSubtreeModified에 "수동"업데이트를 적용하는 것입니다. 값 :

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

(여하튼, 이것은 내가 노력보다 복잡한 구조가 발생했던 루핑 원인이됩니다.)

1

직접 DOM을 재생 $를 사용하여 그냥 HTML5 details 태그에 바인딩 양방향을 만들

:-) ko 방법이 아니다, 그것에서 저렴 코.

http://jsfiddle.net/gznf3/

ko.bindingHandlers.disclose = { 
    init: function(element, valueAccessor) { 
     if (element.tagName.toLowerCase() !== 'details') { 
      throw "\"disclose\" binding only works on <details> tag!"; 
     } 
     var value = valueAccessor(); 
     if (ko.isObservable(value)) { 
      $(element).on("DOMSubtreeModified", function() { 
       value($(element).prop('open')); 
      }); 
     } 
    }, 
    update: function(element, valueAccessor) { 
     $(element).prop('open', ko.unwrap(valueAccessor())); 
    } 
}; 
관련 문제