Rendering a recursive structure using a CompositeView while encapsulating each model in an ItemView using Marionette

I will start with a clear question and explain after:
How to properly encapsulate the model contained in CompositeView, inItemView

My problem is simple, but I can’t get something good. I have a Notes tree. Each note - this is a collection of Backbone.model and @descendants then I have Backbone.Collection, to present a tree (of which @descendants - copy) I set up a base CollectionView, with like ItemView, CompositeView. Everything was perfect and I was very pleased with it. This working solution is shown in the first code snippet!

That is the problem. Based on this, I somehow ran into this problem: Events fired for a whole hierarchy that make sense for how my events are related. Firstly, I just added unique selectors (added data-guid to my html elements so I can get them), and it worked fine, although it has already become “hacked”. But another similar problem came up, so I decided that I needed a solution for this. So, I said myslef, let it encapsulate each model in the ItemView and use the Composite view to render them recursively. But ... It was not for the best in all the worlds ...

Here is what I had at the beginning:

class Note.ModelView extends Marionette.CompositeView
  template: "note/noteModel"
  id: "note-item"
  itemViewContainer: ".note-descendants"
  ui:
    noteContent: ".noteContent"
  events:
    "keypress .noteContent": "createNote"
    "click .destroy": "deleteNote"
  # ...
  initialize: ->
    @collection = @model.descendants
  # ...

class Note.CollectionView extends Marionette.CollectionView
  id: "note-list"
  itemView: Note.ModelView
  initialize: ->
    @listenTo @collection, "sort", @render

Now I have passed everything that belongs to the rendering of the model in the new ItemView

  class Note.ModelView extends Marionette.ItemView
    template: "note/noteModel"

    ui:
      noteContent: ".noteContent"
    events: ->
      guid = @model.get 'guid'
      events = {}
      events["keypress #noteContent#{guid}"] = "createNote"
      events["blur #noteContent#{guid}"] = "updateNote"
      events["click #destroy#{guid}"] = @triggerEvent 'deleteNote'

    initialize: ->
      @bindKeyboardShortcuts()
      @listenTo @model, "change:created_at", @setCursor

  class Note.TreeView extends Marionette.CompositeView
    template: "note/parentNote"
    itemView: Note.ModelView

    initialize: ->
      @collection = @model.descendants
      @listenTo @collection, "sort", @render
      _.bindAll @, "renderItem"
    renderItem: (model) ->
      if model.get('parent_id') is 'root'
        itemView = new Note.ModelView model: model
        itemView.render()
        @$el.append itemView.el
    onRender: ->
      @collection.each this.renderItem
      @renderItem @model
    appendHtml: (collectionView, itemView) ->
      @model.descendants.each (note) =>
        iv = new Note.ModelView model: note
        iv.render()
        @.$('.note-descendants').append iv.el


  class Note.CollectionView extends Marionette.CollectionView
    id: "note-list"
    itemView: Note.TreeView
    initialize: ->
      @listenTo @collection, "sort", @render

and noteMode template (parentNote is just an empty template)

<button class="btn btn-danger btn-xs untab">UN</button>
<button class="btn btn-success btn-xs tab">TAB</button>
<div class="noteContent">{{{indent}}}{{{title}}}</div>
<button class="destroy"></button>
<div class="note-descendants"></div> # That is where I'm putting the children notes

. ... , . , Derick Bailey CompositeView David Sulc on Nested Views, , .

, , Marionette. - , angular, .
, ? !

. .

+4
1

, , , .

.

-, " " - , . Marionette.CollectionView, Marionette.CompositeView.

- , Marionette.CompositeView. Marionette.CompositeView, itemView. itemView, Marionette.CompositeView ITSELF , .

Collection

, Backbone.Collection Backbone.Collections, Backbone.Collection, . Backbone.Collections Marionette.CompositeView( Initialize() RecursiveView).

var RecursiveView = Marionette.CompositeView.extend({
    template: '#someTemplate',
    initialize: function () {
        this.collection = this.model.get('children')
    }
});

var MotherView = Marionette.CollectionView.extend({
    itemView: RecursiveView,
    collection: new Backbone.Collection([{key: 'value', children: [{}, {}, {}]}])
});

: Bubbling

, DOM ,

var RecursiveView = Marionette.CompositeView.extend({
    events: {
        'click button': someCallback
    }
});

, , .

- css selectr >, .

var RecursiveView = Marionette.CompositeView.extend({
    events: {
        'click >button': someCallback
    }
});

, , ,

var RecursiveView = Marionette.CompositeView.extend({
    events: {
        'click button': function (event) {
            event.stopPropagation();
            // or event.stopImmediatePropagation() depending on your use case
            // cf. http://stackoverflow.com/a/5299841/899586 and 
        }
    }
});
+3

All Articles