Attach existing views/items to a collection view #180

Closed
Spea opened this Issue Jul 10, 2012 · 5 comments

Comments

Projects
None yet
3 participants
@Spea

Spea commented Jul 10, 2012

Currently I'm using version 0.8.4. When I tried to upgrade to 0.9.3 the attaching of existing items to a collection view stoped working, here is how I solved this in 0.8.4

class ListView extends Backbone.Marionette.CollectionView
  id: "list"
  itemView: SimpleItemView
  tagName: "ul"

  initialize: ->
    @attach()

  attach: ->
    @$("li").each (index, element)=>
      el = $(element)
      id = el.attr("data-id")
      model = App.collection.get(id)
      itemView = new SimpleItemView {
        model: model
        el: el
      }
      @storeChild(itemView)

In 0.9.3 this does not work anymore, since the child view storage is initialized after the call of the initialize function.
I tried to call the attach function after new ListView but there are some other things (e.g. childBindings) which are only assigned, when calling the addItemView function, so I get an error when marionette tries to remove the child views.

How can I solve this? I know I can attach existing views to regions, but is this also somehow possible with a CollectionView? I need to do it this way, because the site needs to be SEO friendly, so the list is already rendered on the server side.

@derickbailey

This comment has been minimized.

Show comment Hide comment
@derickbailey

derickbailey Jul 10, 2012

Owner

a simple workaround for now would be to modify the constructor on the CollectionView to init the child storage immediately

Backbone.Marionette.CollectionView::constructor = () ->
    @initChildViewStorage()
    super(arguments)
    @initialEvents()
    @onShowCallbacks = new Marionette.Callbacks()

I can make this change in an upcoming release, to provide a built-in solution for it. But for now, you'll have to make this change in your app. Just drop that code in to your app somewhere after Marionette is loaded, but before you instantiate any views or anything.

(Note that I'm not a regular coffeescript user, so that might be a bit off in the coffeescript syntax)

Owner

derickbailey commented Jul 10, 2012

a simple workaround for now would be to modify the constructor on the CollectionView to init the child storage immediately

Backbone.Marionette.CollectionView::constructor = () ->
    @initChildViewStorage()
    super(arguments)
    @initialEvents()
    @onShowCallbacks = new Marionette.Callbacks()

I can make this change in an upcoming release, to provide a built-in solution for it. But for now, you'll have to make this change in your app. Just drop that code in to your app somewhere after Marionette is loaded, but before you instantiate any views or anything.

(Note that I'm not a regular coffeescript user, so that might be a bit off in the coffeescript syntax)

@Spea

This comment has been minimized.

Show comment Hide comment
@Spea

Spea Jul 10, 2012

Thanks, this fixed the storage error. Now I'm using the function addItemView instead of storeChild so the bindings will be set correctly. Unfortunately I had to modify renderItemView and buildItemView so I can add an existing ItemView which will not be rendered

Here is the complete code, just in case ;)

Backbone.Marionette.CollectionView::constructor = ->
  @initChildViewStorage();
  Backbone.Marionette.View.prototype.constructor.apply(this, arguments);
  @initialEvents();
  @onShowCallbacks = new Backbone.Marionette.Callbacks();
  return

class ListView extends Backbone.Marionette.CollectionView
  id: "list"
  itemView: SimpleItemView
  tagName: "ul"

  initialize: ->
    @attach()

  renderItemView: (view, index)->
    if view.options.exists == undefined
      super(view, index)

  buildItemView: (item, ItemView)->
    if _.isFunction(ItemView)
      return super(item, ItemView)

    return ItemView

  attach: ->
    @$("li").each (index, element)=>
      el = $(element)
      id = el.attr("data-id")
      model = App.collection.get(id)
      itemView = new SimpleItemView {
        model: model
        el: el
        exists: true
      }
      @addItemView(model, itemView, id)

Spea commented Jul 10, 2012

Thanks, this fixed the storage error. Now I'm using the function addItemView instead of storeChild so the bindings will be set correctly. Unfortunately I had to modify renderItemView and buildItemView so I can add an existing ItemView which will not be rendered

Here is the complete code, just in case ;)

Backbone.Marionette.CollectionView::constructor = ->
  @initChildViewStorage();
  Backbone.Marionette.View.prototype.constructor.apply(this, arguments);
  @initialEvents();
  @onShowCallbacks = new Backbone.Marionette.Callbacks();
  return

class ListView extends Backbone.Marionette.CollectionView
  id: "list"
  itemView: SimpleItemView
  tagName: "ul"

  initialize: ->
    @attach()

  renderItemView: (view, index)->
    if view.options.exists == undefined
      super(view, index)

  buildItemView: (item, ItemView)->
    if _.isFunction(ItemView)
      return super(item, ItemView)

    return ItemView

  attach: ->
    @$("li").each (index, element)=>
      el = $(element)
      id = el.attr("data-id")
      model = App.collection.get(id)
      itemView = new SimpleItemView {
        model: model
        el: el
        exists: true
      }
      @addItemView(model, itemView, id)
@derickbailey

This comment has been minimized.

Show comment Hide comment
@derickbailey

derickbailey Oct 4, 2012

Owner

hi @Spea - sorry it took me so long to get this fixed. i completely forgot about this until i started looking through old tickets again. :(

this is fixed in the dev branch now, and will be released w/ v0.11.0 soon

Owner

derickbailey commented Oct 4, 2012

hi @Spea - sorry it took me so long to get this fixed. i completely forgot about this until i started looking through old tickets again. :(

this is fixed in the dev branch now, and will be released w/ v0.11.0 soon

@Spea

This comment has been minimized.

Show comment Hide comment
@Spea

Spea Oct 4, 2012

I found another workaround for this, so it was not that urgent ;) Thanks for the fix!

Spea commented Oct 4, 2012

I found another workaround for this, so it was not that urgent ;) Thanks for the fix!

@alfredo-cp

This comment has been minimized.

Show comment Hide comment
@alfredo-cp

alfredo-cp Oct 9, 2014

@derickbailey thanks for the spec on this one. Only want to mention if it helps to anybody, storeChild it is not available anymore, I'm using 1.7.2 so this.children.add(view); does the trick now.

@derickbailey thanks for the spec on this one. Only want to mention if it helps to anybody, storeChild it is not available anymore, I'm using 1.7.2 so this.children.add(view); does the trick now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment