Question

I have an API resource that gives me a list of users that each have several items. The hierarchy is like so:

- users
  - user
    - items
      - item
      - item
      - item
  - user
    - items
      - item
      - item
      - item

I would like to display the list of users on a single page, with each user entry displaying each of its items on the page as well.

When any one of these items is clicked, it should set an chosen attribute that is accessible through the overall users collection.

I'm having difficulty getting the item click information to bubble back up. My current implementation is creating a separate items collection in order to render the view, but then I lose the connection to its original user model, so I can't notify it when the item is selected.

My views are structured like so:

class List.Item extends Marionette.ItemView
  template: "path/to/template"

  events:
    "click" : "choose"

  choose: (e) ->
    # what to do?

class List.User extends Marionette.CompositeView
  collection: @collection
  template: "path/to/template"
  itemView: List.Item
  itemViewContainer: "span"

  initialize: ->
    @collection = new App.Entities.Items(@model.get("items"), parent: @)

  events:
    "click a" : "toggleChoose"

  @include "Chooseable"

class List.Users extends Marionette.CollectionView
  itemView: List.User

Is there a better way to structure these collections or views, or is there a way to pass the information from the List.Item view to the parent List.User view and then into the users collection?

EDIT

I have tried backbone-relational, but it didn't seem to quite do what I need. Please correct me if I'm wrong here.

Was it helpful?

Solution 2

It is actually possible to instantiate the items collection to reference the parent user and vice-versa directly in Backbone:

class Entities.User extends Backbone.Model
  ...
  initialize: ->
    @items = new Entities.Items @get("items"),
      user: @

class Entities.Items extends Backbone.Collection
  ...
  initialize: (models, options) ->
    @user = options?.user

So now the List.User CompositeView can pass this information to the List.Item ItemView:

class List.User extends Marionette.CompositeView
  collection: @collection
  ...
  initialize: ->
    @collection = @model.items

With this in place, it is possible to access the user directly from the ItemView:

class List.Item extends Marionette.ItemView
  ...
  events:
    "click" : "choose"

  choose: (e) ->
    e.preventDefault()
    user = @model.collection.user
    console.log "user: ", user

And from there it's possible to take any necessary actions on the user and its collection.

OTHER TIPS

Your List.Item should contain it's current model with all properties at the time when choose is triggered. In this way, you can trigger other events with the List.Item's model values:

choose(e) : ->
  trigger("mylistitem:choose", model)

Then listen for the event elsewhere :

itemView.on("itemview:mylistitem:choose", ( childView, model ) -> {
 alert(model.get('..whatever..')
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top