0

In Marionette, we have a "master view" that we would like to extend.

var PaginatedDropdown = Marionette.CompositeView.extend({
  template: template,
  events: {
    'click': function () { return 'hello';},
    'keyup': function () { return 'goodbye'}
  },
  childViewOptions: {
     tagName: 'li'
  }
});

The ideal use case would be extending this view, or class, by more specific views that would implement most of the features, and modify some of the features, of the master class / view:

var MotorcycleColorChooserDropdown = PaginatedDropdown.extend({
    events: {
      'mouseenter': function () { return 'vroom'; };
    }
});

The problem is we're not sure how to selectively modify things such as the events hash, or override certain childview options. Specifically:

  1. If MotorcycleColorChooserDropdown has an events object, it will override all of the events the PaginatedDropdown is listening for. How do we mix and match? (allow having an events object on MotorcycleColorChooserDropdown that combines itself with PaginatedDropdown's events object?

  2. Potentially unsolvable: What if we want all the functionality of the PaginatedDropdown click event, but we also want to add to it a little bit in MotorcycleColorChooserDropdown? Do we just have to manually stick all the functionality from the Parent into the Child class?

We have considered simply not doing extended views like this, or doing things like MotorcycleColorChooserDropdown = PaginatedDropdown.extend(); and then one at a time doing MotorcycleColorChooserDropdown.events = PaginatedDropdown.events.extend({...}); but that seems messy, ugly, and I'm sure there's a better way.

Caleb Jay
  • 2,159
  • 3
  • 32
  • 66

2 Answers2

2

Here is what i've been doing

var PaginatedDropdown = Marionette.CompositeView.extend({
  template: template,
  events: {
    'click': 'onClick',
    'keyup': function () { return 'goodbye'}
  },
  onClick:function(e){
      return 'hello'
  },
  childViewOptions: {
     tagName: 'li'
  }
});

var MotorcycleColorChooserDropdown = PaginatedDropdown.extend({
    events: _.extend({
      'click': 'onClick',
      'mouseenter': function () { return 'vroom'; };
    },PaginatedDropdown.prototype.events),
    onClick:function(e){
        PaginatedDropdown.prototype.onClick.call(this,e)
        //code
    }
});

For your first question, i just extend the child events with the parent events.

As for the second, i just call the parent method from the child, passing in the child context and the event object.

It is quite verbose, but also very explicit. Someone reading your code will know exactly what's going on.

Eric Guan
  • 15,474
  • 8
  • 50
  • 61
  • You're right, except for `...events.extend({...});` which doesn't exist. The `extend` function is from Backbone and doesn't work on every object. – Emile Bergeron Apr 20 '17 at 02:18
  • 1
    You're right, I looked at the code's intent rather than its correctness, will edit my answer. – Eric Guan Apr 20 '17 at 02:38
0

You could:

var PaginatedDropdown = Marionette.CompositeView.extend({
   template: template,
   childViewOptions: {
     tagName: 'li'
   },
   "events": function() {
     'click': 'onClick',
     'keyup': 'onKeyUp'
   },
   "onClick": function() {
      return 'hello';
   },
   "onKeyUp": function() {
      return 'hello';
   },
}); 

var MotorcycleColorChooserDropdown = PaginatedDropdown.extend({
    "events" : function() {
      //Question: 
      //Basically extending the first events by using the marionette event function and extending it.
      var parentEvents = PaginatedDropdown.prototype.events,
          events = _.extend({}, parentEvents);

      events['mouseenter'] = this.onMouseEnter;
      //add all of the events of the child
      return events;
    }
    "onMouseEnter": function() {
      return 'vroom';
    },
    "onClick": function() {
       //Question 2: 
       //Applying the parent's method
       PaginatedDropdown.prototype.onClick.apply(this, arguments);

       //and adding new code here
   }
});