javascriptbackbone.jsmarionettebackbone-events

SerializeData in CompositeView


I need to pass a value to the listView.template in order to be aware the template about the collection.length.
I think one option is to redefine the serializeData method in order to pass a parameter in this way.

var ListView = Marionette.CompositeView.extend({

    initialize: function () {
        this.collection.on('reset', this.serializeData, this);
        this.collection.on('remove', this.serializeData, this);
        this.collection.on('add', this.serializeData, this);
    },

    serializeData: function () {
        console.log(this.collection.length);
        return {
            has_tasks: this.collection.length > 0
        };
    },

    // other codes
});

When I start the app the collection is not yet fetched so:

1.a) the collection.legth = 0
2.b) the template get has_tasks = false as expected.

2.a) after the fetch the collection.length is > 0,
2.b) the serializeData is called and so it puts the has_tasks = true,
2.c) the template seems to be not rendered because it maintains the has_tasks = false

Any idea because 2.c?


Solution

  • Latest Marionette has solved this problem by calling an optional templateHelpers on the view to provide additional context to the view. Also your event binding is not Marionette-friendly as it it will not be auto-unbound correctly when the view is unloaded. So all you need to do in your view is:

    var ListView = Marionette.CompositeView.extend({
    
        initialize: function () {
            this.bindTo(this.collection, "add", this.render, this);
            this.bindTo(this.collection, "remove", this.render, this);
            this.bindTo(this.collection, "reset", this.render, this);
        },
    
        templateHelpers: function () {
            console.log(this.collection.length);
            return {
                has_tasks: this.collection.length > 0
            };
        },
    
        // other codes
    });
    

    Note, however, that you probably don't want to rerender the entire view and all the sub-elements every time an item is added or removed. A better approach is to only update the count displayed. For instance:

    var ListView = Marionette.CompositeView.extend({
    
        initialize: function () {
            this.bindTo(this.collection, "add", this.updateCount, this);
            this.bindTo(this.collection, "remove", this.updateCount, this);
            this.bindTo(this.collection, "reset", this.updateCount, this);
        },
    
        updateCount: function() {
            this.$('.count_span').html(this.collection.length);
        },
    
        // other codes
    });