2014-01-07 2 views
1

처음으로 Marionette을 사용하여 CompositeView를 렌더링하고 렌더링 할 때 'itemViewContainer'속성과 관련된 문제가 발생했습니다.백본 Marionette 'itemViewContainer'을 찾지 못했습니다.

같은 응용 프로그램에서 작동하도록 CompositeView를 얻었지만,이 경우 사용자가 버튼을 클릭 할 때 'PopupView'를 렌더링하려고합니다. 이 팝업에는 CompositeView가 나타나지 않는 표가 있습니다.

다음은 사용자가 팝업을 열 수있는보기입니다. 이것은 CompositeView의 항목입니다. 여기

define([ 
    'marionette', 
    'templates', 
    'views/SectionPopupView' 
], function(
    Marionette, 
    templates, 
    SectionPopupView 
) { 

    /** ClassListingRowView represents a row in the ClassListingView. 
    * Each Row is tied to a specific Course object that's passed in 
    * when the Row is instantiated in ClassListingView. 
    * this.model: Course model 
    * this.options.user: User model */ 
    return Marionette.ItemView.extend({ 
    template: templates.classListingRow, 
    className: 'class-listing', 
    popupView: null, 

    ui: { 
     'editBtn': 'a.edit-btn', 
     'removeBtn': 'a.remove-btn', 
     'popupContainer': 'div.popup-container' 
    }, 

    events: { 
     'click @ui.editBtn': 'editCourse', 
     'click @ui.removeBtn': 'removeCourse' 
    }, 

    /** Set the ID of this element to [UID]-listing. Also fetches data 
    * from the model. */ 
    // TODO: This calls render() twice... how do I make it better? 
    initialize: function() { 
     this.user = this.options.user; 
     $(this.$el).attr('id', this.model.get('UID') + '-listing'); 

     var self = this; 
     this.model.fetch({ 
     success: function() { 
      self.render(); 
     } 
     }); 
    }, 

    /** Spawns a popup with all sections that allows a user to choose 
    * which sections he/she does/doesn't want. */ 
    editCourse: function(e) { 
     e.preventDefault(); 
     e.stopPropagation(); 

     var self = this; 
     // Instantiate a view if it hasn't already been instantiated 
     $(window.app.curtain).show(); 
     if (this.popupView == null) { 
     this.popupView = new SectionPopupView({ 
      el: self.ui.popupContainer, 
      model: self.model 
     }); 
     this.popupView.render(); 
     } else { 
     this.popupView.show(); 
     } 
    }, 

    /** Removes this.course from the User's selectedCourse list. 
    * This will trigger an event which the ClassListingView should be 
    * listening for, and then this View will be discarded. */ 
    removeCourse: function(e) { 
     e.preventDefault(); 
     e.stopPropagation(); 

     this.user.removeCourseFromSelected(this.model); 
    } 
    }); 
}); 

가 팝업보기입니다 :

define([ 
    'marionette', 
    'templates', 
    'views/PopupView', 
    'views/SectionTableView', 
    'jquery' 
], function(
    Marionette, 
    templates, 
    PopupView, 
    SectionTableView, 
    $ 
) { 

    /** A SectionPopupView is a View that represents a popup that shows all of 
    * the sections for a particular Course and allows a user to select 
    * which sections he wants to include and also to see more information 
    * about the course. 
    * model: Course */ 
    var SectionPopupView = PopupView.extend({ 
    template: templates.sectionPopup, 
    sectionTable: null, 

    ui: { 
     'closeBtn': 'a.close', 
     'tableContainer': 'div#table-container', 
     'okBtn': 'a#submit' 
    }, 

    events: { 
     'click @ui.closeBtn': 'close', 
     'click @ui.okBtn': 'continue' 
    }, 

    /** Upon initialization, the View will have been instantiated with 
    * model: Course. A SectionListTableView must be instantiated upon 
    * init and populated with data from the model's sections attr. */ 
    initialize: function() { 
     var self = this; 
     this.on('render', function() { 
     self.sectionTable.render(); 
     }); 
     this.sectionTable = new SectionTableView({ 
     el: self.ui.tableContainer, 
     model: self.model 
     }); 

     // this.sectionTable.render(); 
    }, 

    /** Hides the popup (and curtain). */ 
    show: function() { 
     $(window.app.curtain).show(); 
     $(this.el).show(); 
    }, 

    /** Shows the popup (and curtain). */ 
    close: function(e) { 
     e.preventDefault(); 
     e.stopPropagation(); 

     $(window.app.curtain).hide(); 
     $(this.el).hide(); 
    } 
    }); 

    return SectionPopupView; 
}); 

여기에 테이블의보기이다 (sectionTable는)

define([ 
    'marionette', 
    'templates', 
    'views/SectionTableRowView', 
    'views/NoSectionsView', 
    'jquery' 
], function(
    Marionette, 
    templates, 
    SectionTableRowView, 
    NoSectionsView, 
    $ 
) { 

    /** 
    * this.model = Course */ 
    return Marionette.CompositeView.extend({ 
    template: templates.sectionTable, 
    itemView: SectionTableRowView, 
    itemViewContainer: 'tbody', 
    emptyView: NoSectionsView, 

    initialize: function() { 
     this.itemViewOptions = { 
     user: this.model 
     }; 
    } 
    }); 
}); 

나는 많은 사람들이이 문제를하였습니다 여기에 읽기 그들은 DOM에 있기 전에 뷰를 렌더링하려고했기 때문에 테이블의 render 함수를 팝업의 render 이벤트에 바인딩했지만 그 역시 작동하지 않았습니다. 어떤 도움이 필요합니까?

그 외에도 MVC 가이드 라인/모범 사례/기타와 관련하여 잘못하고 있습니까? 나는 내 코드에 100 % 자신감이 없기 때문에 피드백도 환영 할 만하다! 감사.

답변

0

몇 가지 :

this.on("render", function() { 
    this.sectionTable.render(); 
}, this); 

이 모든 비트의 onRender 기능으로 이동 될 수있다 :

1) 귀하의 this.on("render"... 코드는 바로 컨텍스트 (나는이 작품 생각)을 통과해야 선명도에 도움이보기 : 그것은 이해하는 것이 중요

onRender: function() { 
    this.sectionTable.render(); 
} 

2) 어떤 꼭두각시 신호 DOM을 주위에 사용 :

onRender 방법은 뷰에 대한 $el 완전히 가상 DOM에 건설 된 때 호출하지만, 얻을 그것은 사용자의 (접근/jQuery를) DOM

에 삽입되기 전에

onShow 방법은 그의 $el 호출받을 뷰가 DOM에 성공적으로 있고 jQuery에 액세스 할 수 있습니다.

대개 레이아웃을 중첩하는 경우에만 발생하는 onShow 가장자리 케이스가 있습니다. 나는 호기심이 있다면 here라고 적었습니다.

+0

'onRender'와'onShow'에 대한 정보를 보내 주셔서 감사합니다. 나는 코드를 onRender로 옮겼지만 여전히 'itemViewContainer'오류를 찾을 수 없다. 지역을 사용하여 팝업을 표시하지 않으므로 onShow 메서드가 없습니다. – Dennis

+0

문제를 다시 요약하자면, SectionTable 뷰는 item 뷰 추가를 수행 할 것으로 예상되는 $ el에서 'tbody'를 찾을 수 없기 때문에 갑자기 나타납니다. 해당 뷰에 사용되는 템플릿에 'tbody'요소가 지정되어 있는지 확인할 수 있습니까? –

+0

이렇게 늦은 답변을 드려 죄송합니다. 예, 템플릿에 tbody라는 요소가 있습니다. 여기서'initialization '함수에'this.template'를 기록했는데 내부에'tbody'가 분명히 있지만 여전히 오류가 있습니다. http://d.pr/i/EA07 – Dennis

관련 문제