1
votes

I'd like my composite to automatically render a collection, which it already does. However I'd also like it to fetch a model for me and give the composite access to that model.

Basically I'm trying to render a users details with a collection of clients below.

CompositeView

define([
  "marionette",
  "text!app/templates/user/view-clients/collection.html",
  "app/collections/users/clients",
  "app/views/user/view-clients/item",
  'app/models/user'
],
  function(Marionette, Template, Collection, Row, Model) {
    "use strict"
    return Backbone.Marionette.CompositeView.extend({
      template: Template,
      itemView: Row,
      itemViewContainer: "#stage-user-clients",
      collectionEvents: {
        'sync': 'hideLoading'
      },
      initialize: function (options) {
        this.showLoading()

        this.model = new Model({_id: options.id})
        this.model.fetch() 

        this.collection = new Collection()
        this.collection.queryParams = {_id: options.id}

        return this.collection.fetch()
      },
      showLoading: function() {
        this.$el.addClass('loading')
      },
      hideLoading: function() {
        this.$el.removeClass('loading')
      }
    })
  })

ItemView

define(["marionette", "text!app/templates/user/view-clients/item.html"], function(Marionette, Template) {
  "use strict"
  return Backbone.Marionette.ItemView.extend({
    template: Template,
    tagName: "li"
  })
})

Would I need to basically manage the render method myself or create a separate view for the model and manually bind that to an id inside the composite template?

1

1 Answers

4
votes

You'd probably be better not instanciating your collections/models from inside your views.

var MyCompositeView = Backbone.Marionette.CompositeView.extend({
    initialize: function() {
        // The collection is already bound, so we take care only of the model
        // Both will be rendered on model change, though
        this.listenTo(this.model, 'change', this.render, this);

        // If you want to rerender the model only, use this instead :
        this.listenTo(this.model, 'change', function(){
            this.$el.html(this.renderModel());
        }, this);
    }
    ...
});

var myCollection = new Collection({url: '/collection/'});
var myModel = new Model({url: '/model/', id: 1});

var myCompView = new MyCompositeView({model: myModel, collection: myCollection});

myModel.fetch();
myCollection.fetch({reset: true});

This is roughly what it may look like. If in doubt, look into backbone's source.