2012-08-09 3 views
0

저는 Backbone의 세계에서 아주 새롭고 저의 첫 번째 심각한 프로젝트에 Marionette을 사용하기로 결정했습니다.Backbone.Marionette : collection.reset()이 실행 된 후에 CompositeView가 사라집니다.

몇 가지 어려움과 함께 나는 내 애플 리케이션의 기본 옵션과 라우팅을 설정할 수 있었고 꽤 행복했지만 지금은 테이블을 나타내는 CompositeView에 대한 블로킹 문제에 직면 해있다.

이보기는 "그리드"라는 특정 레이아웃의 영역 내에 렌더링됩니다. 이 레이아웃에는 top_controls, table_view 및 bottom_controls의 3 개의 영역이 있습니다. 레이아웃의 일부 요소에 일부 액션을 바인딩해야하므로 뷰로 사용하고 "마스터"컬렉션을 내부에 포함하기로 결정하여 CompositeView 내부에서 컬렉션의 필터링 된 버전을 렌더링 할 수 있습니다. 주된 것을 건드리지 않고. 나는이 방법으로 호출 내 라우터에서

:

App.grid = new Grid({collection: Clt}); 
App.page.show(App.grid); 

레이아웃의 구조는이 (내가 사용 requireJS)입니다 :

var Grid = Backbone.Marionette.Layout.extend({ 

     className: "container-fluid", 

     template: gridLayout, 

     regions: { 
      top_controls: "#top_controls", 
      table_view: "#table_view", 
      bottom_controls: "#bottom_controls", 
     }, 

      initialize: function(){ 

       this.renderTable(this.collection, true);     
      }, 

      renderTable: function(collection, fetch){ 

       if(fetch){ 

        collection.fetch({success:function(){ 

         var vista = new CompView({collection: collection});        
         App.grid.table_view.show(vista); 

        }}); 

       } else { 

        var vista = new CompView({collection: collection});      
        App.grid.table_view.show(vista);      
       } 
      }, 

      events: { 
       "keyup input":"filter_grid" 
      }, 

      filter_grid: function(e){ 

       var $el = e.currentTarget; 
       var to_filter = $($el).val(); 

       if(to_filter==""){ 

        this.renderTable(this.collection, false); 

       } else { 

        var filtered = this.collection.filter(function(item){ 
         return item.get("link_scheda").toLowerCase() == to_filter; 

        }); 

        if(filtered.length>0){ 

         var filtro = new AssocCollection(); 

         filtro.reset(filtered); 

         this.renderTable(filtro, false); 
        } 
       }     
      } 
    }); 

    return Grid; 

레이아웃 템플릿은 다음과 같습니다 :

<div class="row-fluid" id="top_controls"><input type="text" id="filter" class="input"/></div> 
<div class="row-fluid" id="table_view"></div> 
<div class="row-fluid" id="bottom_controls"><button class='add btn btn-primary'>Add</button></div> 

내의 CompositeView가 그렇게 구성되어있다 :

var AssocView = Backbone.Marionette.CompositeView.extend({ 

    tagName: 'table', 
    className: 'table table-bordered table-striped', 
    id: 'tableAssoc', 
    template: assocTemplate, 
    itemView: assocRow, 

    appendHtml: function(collectionView, itemView, index){ 
     collectionView.$("tbody").append(itemView.el); 
    }, 

    events: { 
     "click .sort_link":"sort_for_link", 
    }, 

    sort_for_link: function(){ 

     this.collection.comparator = function(model){ 

      return model.get("link_value"); 
     } 

     this.collection.sort(); 

    }, 

    onRender: function(){ 
     console.log("render table!"); 

    } 

}); 

return AssocView; 

테이블의 첫 번째 표시가 올바르게 수행되고 필터링도 수행됩니다. 문제가 발생하면 "sort_link"클래스가있는 표 머리글을 클릭하면 컬렉션이 그대로 유지되는 동안 전체 표가 HTML에서 지워집니다 (전체 레이아웃은 다시 렌더링 됨). 예를 들어 CompositeView를 응용 프로그램 주 영역과 같은 다른 위치에 렌더링하면 모두 의도 한대로 작동합니다. 그래서 내 레이아웃 선언 안에 문제가있는 것 같아요.

도움이 될 것입니다.

답변

0

GridinitialEvents 메서드를 무시하고 아무 것도 수행하지 않아야합니다.


Grid = Backbone.Marionette.Layout.extend({ 

    initialEvents: function(){}, 

    // ... everything you already have 

}); 

레이아웃 ItemView에서 확장하고 ItemView는 initialEvents 구현을 제공합니다. 이 메소드는 콜렉션이 주어 졌는지 여부를 검사하고 콜렉션이 주어지면 컬렉션의 "reset"이벤트를 뷰의 "render"메소드에 연결합니다. 귀하의 경우, 당신은 컬렉션을 통과하고 있으며 이러한 행동을 원하지 않습니다. 따라서 initialEvents 메서드를 재정 의하여이를 수정합니다.

업데이트 : 나는 그 전에 initialEvents을 삭제했다고 생각했습니다. 마리오네트 버전으로 최신 버전을 유지한다면 v.9.10 (또는 최신 버전이 무엇이든) 잡아라. 그러면이 문제는 이제 사라졌다.

+0

감사! 문제는 컬렉션의 재설정 이벤트이지만, 레이아웃보기에 연결하지 않았다는 것을 알았습니다. 라이브러리를 신속하게 업데이트 해 주셔서 감사합니다. :) – Ingro