最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - templateHelpers in Marionette.CompositeView - Stack Overflow

programmeradmin2浏览0评论

I have no idea why this code is not working.
Reading the documentation,
the templateHelpers should be called.

My goal is to pass the this.collection.length to the template.

Any hints? thanks.

I am using Backbone.Marionette v0.9.5


return Marionette.CompositeView.extend({
    className: 'user-board',

    template: usersTemplate,

    itemView: userItemView,

    initialize: function () {
        this.collection = new UseList();
        this.collection.fetch();
    },

    appendHtml: function (collectionView, itemView) {
        collectionView.$el.find('ul.users-list').append(itemView.el);
    },

    templateHelpers: function () {
        console.log(this.collection.length);
    },

    serializeData: function () {
        return {
            weekly: this.options.weekly,
            users_length: this.collection.length // here the length is zero
                                           // after the fetch the length is > 0
                                           // but in template remains 0
        };
    }
});

To fix my issue I have to make the following...

    initialize: function () {
        _.bindAll(this, 'render');
        this.collection = new NewCollection();
        this.collection.fetch({
            success: this.render
        });
    }

Is there a better way to make it working?

I have no idea why this code is not working.
Reading the documentation,
the templateHelpers should be called.

My goal is to pass the this.collection.length to the template.

Any hints? thanks.

I am using Backbone.Marionette v0.9.5


return Marionette.CompositeView.extend({
    className: 'user-board',

    template: usersTemplate,

    itemView: userItemView,

    initialize: function () {
        this.collection = new UseList();
        this.collection.fetch();
    },

    appendHtml: function (collectionView, itemView) {
        collectionView.$el.find('ul.users-list').append(itemView.el);
    },

    templateHelpers: function () {
        console.log(this.collection.length);
    },

    serializeData: function () {
        return {
            weekly: this.options.weekly,
            users_length: this.collection.length // here the length is zero
                                           // after the fetch the length is > 0
                                           // but in template remains 0
        };
    }
});

To fix my issue I have to make the following...

    initialize: function () {
        _.bindAll(this, 'render');
        this.collection = new NewCollection();
        this.collection.fetch({
            success: this.render
        });
    }

Is there a better way to make it working?

Share Improve this question edited Jul 30, 2012 at 8:56 Lorraine Bernard asked Jul 27, 2012 at 14:58 Lorraine BernardLorraine Bernard 13.5k23 gold badges85 silver badges138 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 3

Reading the Marionette Documentation serializeData method, which is the one using mixinTemplateHelpers, is only called on Item View.render method here and in your current code you do not render at all

UPDATE: This way everytime the collection receives new data it will update your view the new length

initialize: function () {
    _.bindAll(this, 'render');
    this.collection = new NewCollection();
    this.collection.fetch();
    this.collection.bind('reset', this.render);
}

This code only declares the a view. Can you share the code the instantiates the view and displays it? templateHelpers will be called and the data passed to the template when the template is rendered. That is, you either need to show the view in a region which implicitly calls the render method on the view, or explicitly call the render method.

To be useful, templateHelpers should return an object. For instance:

templateHelpers: function() {
    return {colLength: this.collection.length};
}

One important thing to keep in mind: fetch trigger an AJAX request that is done asynchronously. If you want to wait for the fetch to succeed before rendering the view, then you need to use Marionette.Async.


Update based on the update question

To avoid calling render from the view's initialize and only do it when render is called externally, change your code to:

return Marionette.CompositeView.extend({
    className: 'user-board',

    template: usersTemplate,

    itemView: userItemView,

    initialize: function () {
        this.collection = new UseList();
        var that = this;
        this.defer = $.Deferred();
        this.collection.fetch({
            success: that.defer.resolve,
            error: that.defer.resolve
        });
    },

    appendHtml: function (collectionView, itemView) {
        collectionView.$el.find('ul.users-list').append(itemView.el);
    },

    templateHelpers: function () {
        console.log(this.collection.length);
        // For greater flexibility and maintainability, don't override `serializeData`.
        return {
            weekly: this.options.weekly,
            users_length: this.collection.length
        };
    },

    render: function() {
        var that = this,
            args = arguments;
        $.when(this.defer).done(function() {
            Marionette.CompositeView.prototype.apply(that, args);
        });
    }
}); 

I'm resolving this.render both on success and error, otherwise if there is an error the view will never render (unless that's what you want).

Note that if you use Marionette.Async then you would return this.defer in the view's beforeRender and Marionette.Async would take care of delaying the rendering.

Also note that once this.defer is resolved, future renders will run when called as there is nothing to wait for, until this.defer has been reset programmatically.

At least in Marionette v1.0.3, I'm liking the pattern that rendering is handled automatically during a call to Region.show(), so I call that from a controller object which has the collection and passes it to the view on instantiation then shows the view. I don't even have to put this logic in a fetch success callback or explicitly bind to the 'reset' event, because the Marionette posite/collection view already knows to (re-)render itself on fetch success (which a debugger will show you).

After using a setup like has been detailed, you can also use template helpers a bit more usefully than has been described so far.

For example,

If you simply drop in <%= functionName %> into the template where you are trying to get the number to show up visually on the front end page (since you want .length I see), marionette will simply do the work for you.

So like this:

--Template File--
<div id="followerCount"> <%= showCount %> </div>


--Helper Function in View--
templateHelpers: {
    showCount: function(){
                   return this.collection.length;
    } 
}

Hope that made sense or at least helps someone else perhaps looking for a simpler way to integrate database returned json to their templates.

发布评论

评论列表(0)

  1. 暂无评论