Marionette CollectionView在collection.fetch之后不再重新渲染

时间:2016-02-03 15:06:41

标签: javascript backbone.js underscore.js marionette frontend

我有一封电子邮件'样式应用程序,显示按日期分组的消息。当应用程序加载时,将获取浅层消息集并将其加载到主干集合中。集合中的每个模型都代表一个分组中的消息列表。 MessageGroup代表一组消息,MessagesView显示消息组。

这一切都很有效,直到再次提取集合,就像应用过滤器后一样,只显示组标题,而不是内部的消息。我已经尝试触发MessagesView可以侦听的事件,然后重新渲染自己,但我收到错误:listening.obj.off is not a function

var MessageModel = Backbone.Model.extend({});
var MessageCollection = Backbone.Collection.extend({
    model: MessageModel
});

var GroupModel = Backbone.Model.extend({});
var GroupCollection = Backbone.Collection.extend({
    model: GroupModel,
    url: '/messages/recipient',
    parse: function (response) {

        // Create a grouped JSON to render nested views with
        var messageArray = [];
        var groupedlist = _.groupBy(response.messages, function(model) {
            return model.publishDate;
        });

        _.forEach(groupedlist, function(n, key) {
            var grouping = {};
            grouping.group = key;
            grouping.list = n;
            messageArray.push(grouping);
        });

        return messageArray;
    },
    fetchMessages: function() {
        this.fetch({
            data: filtermodel.toJSON(),
            success: function() {

                var messagecollection = new MessageCollection();

                // Loop through each grouping and set sub-collections
                groupcollection.each(function(group) {
                    var list = group.get('list');

                    messagecollection.reset(list);
                    group.set('list', messagecollection);
                });
            }
        });
    }
});

// Model to track applied filters
var FilterModel = Backbone.Model.extend({
    defaults: {
        folder: 0
    }
});

// ------------------------  VIEWS  ------------- //

// View for a single Message
var MessageView = Backbone.Marionette.ItemView.extend({
    template: require('../../../templates/activities/message-item.ejs'),
    events: { 'click li.item': 'getMessageDetail' },
    getMessageDetail: function(e){
        this.triggerMethod('showDetail', this.model);
        //initMessageDetail(this.model);
    }

});

// Grouped container view for a list of Messages within a group
var MessageGroup = Backbone.Marionette.CompositeView.extend({
    template: require('../../../templates/activities/message-list.ejs'),
    className: "list-view-group-container",
    childView: MessageView,
    childViewContainer: "ul.viewcontainer",
    initialize: function() {
        this.collection = this.model.get('list');

    }

});

// Top level view for all grouped messages
var MessagesView = Backbone.Marionette.CollectionView.extend({
    childView: MessageGroup,
    initialize: function() {
        this.collection.on('change', this.log, this);
    },
    log: function() {
        console.log('triggered log');
    }
});

// View for selected message detail
var MessageDetailView = Backbone.Marionette.ItemView.extend({
    template: require('../../../templates/activities/message-detail.ejs'),
    className: "message-content-wrapper"
});

// View for filter selection bar
var MessageFilterView = Backbone.Marionette.ItemView.extend({
    template: require('../../../templates/activities/message-filter-bar.ejs'),
    events: {
        'click #search-btn': function() {
            filtermodel.set('search', $('#search-input').val());
            groupcollection.fetchMessages();
        }
    }
});


var filtermodel = new FilterModel();
var groupcollection = new GroupCollection();

// Fetch messages first run
groupcollection.fetchMessages();


// LayoutView to display in center panel of application
module.exports = ViewMessages = Marionette.LayoutView.extend({
    template: require('../../../templates/activities/viewmessages.ejs'),
    className: 'content full-height',
    regions: {
        'messagelistregion': '#messageList',
        'messagedetailregion': '.message-detail',
        'messagefilterregion': '.filter-bar'
    },
    childEvents: { 'showDetail': 'onMessageSelected' },
    onMessageSelected: function (childView, childViewModel) {

        var that = this;

        var detailModel = childViewModel.clone();
        var messageDetailView = new MessageDetailView({model:detailModel});
        that.messagedetailregion.show(messageDetailView);
    },
    onShow: function(){

        var that = this;
        var messagesview = new MessagesView({
            collection: groupcollection
        });

        var messageFilterView = new MessageFilterView();
        that.messagelistregion.show(messagesview);
        $("#messageList").ioslist();

        that.messagefilterregion.show(messageFilterView);
        this.messagedetailregion.on('show', function() {
            console.log('message detail region shown:' + that.messagedetailregion.currentView);
        })
    }
});

我正在思考它,因为在触发重置事件并刷新视图之前,在成功回调中构建消息分组所做的工作还没有完成。如何在后续提取后让MessagesView更新?

更新 我将集合的后成功逻辑转移到了它的分层树/叶结构中,转移到顶级集合视图(MessagesView)中的自定义事件(fetchSuccess):

var MessagesView = Backbone.Marionette.CollectionView.extend({
    childView: MessageGroup,
    initialize: function() {
        this.collection.on('fetch:success', this.fetchSuccess, this);
    },
    fetchSuccess: function() {
        var messagecollection = new MessageCollection();

        groupcollection.each(function(group) {
            var list = group.get('list');

            messagecollection.reset(list);
            group.set('list', messagecollection);
        });
    }
});

它在fetch的成功回调中被触发。我很确定这是渲染集合的好方法,但我似乎无法解决Marionette中的错误:

**Uncaught TypeError: listening.obj.off is not a function**

任何人都有任何想法为什么这个collectionview不会重新渲染?

1 个答案:

答案 0 :(得分:1)

我能够确定集合中模型的创建发生在重置事件之后,但是在构建嵌套模型的结构之前:

success: function() {

    var messagecollection = new MessageCollection();

    // Loop through each grouping and set sub-collections
    groupcollection.each(function(group) {
        var list = group.get('list');

        messagecollection.reset(list);
        group.set('list', messagecollection);
    });
};

在任何过滤事件,分组,排序等之后,每次都需要将集合结构修改为此嵌套层次结构。视图在构建结构之前拾取重置事件,因此子视图没有要呈现的数据。我通过在更改后克隆原始集合并让视图呈现克隆集合来修复此问题:

groupcollection.fetch({
    reset: true,
    data: filtermodel.toJSON(),
    success: function() {

        groupcollection.each(function(group) {
            var list = group.get('list');

            var messagecollection = new MessageCollection(list);
            group.set('list', messagecollection);
        });

        filteredcollection.reset(groupcollection.toJSON());
    }
});