Search code examples
javascriptlayouttriggersmarionetteevent-bubbling

itemView trigger a custom event reaching the parrent


I have this code http://jsfiddle.net/QRcF5/2/

$(function() {
    var Header = Backbone.Marionette.ItemView.extend({
        template: _.template('<h4>TEST</h4><button>EDIT</button>'),

        tagName: 'nav',

        triggers: {
            'click button': 'btn_clicked'
        }
    }),
    Layout = Backbone.Marionette.Layout.extend({
        template: _.template('<header></header>'),

        regions: {
            header: 'header'
        },

        events: {
            'itemview:btn_clicked': 'clicked'
        },

        clicked: function() {
            alert('Ana are mere');
        }
    });

    layout = new Layout();
    $('body').append(layout.render().el);
    layout.header.show(new Header());
});

I'm using a layout with one ItemView (later I want a more complex nesting) and want to capture in LAYOUT the event that is happening in the ITEMVIEW. It seems its not bubbling upwards or I'm doing something wrong here.


UPDATE 1 I've tried events, triggers (for the child) and on, events (for the parent) but I still can't get the event caught inside the parent.

I can use:

_.extend(App.vent, Backbone.Events);

Backbone.Marionette.ItemView.extend({
    ....
    App.vent.trigger('btn_clicked');
    ....
});

Backbone.Marionette.Layout.extend({
    ....
    App.vent.on('btn_clicked', function() { doCoding(); });
    ....
});

But this way I'm breaking the encapsulation. Is there a way to keep the encapsulation by using Marionette triggers eventing and keep it all in the layout and not polluting the entire app ?


UPDATE 2

http://jsfiddle.net/QRcF5/5/

I've update the jsfiddle to use the _.extend(vent, Backbone.Events). If anyone has a better pattern for this, please let us know :D


Solution

  • I've found the solution (buried somewhere in the documentation making some connections between layout, region and view) !

    http://jsfiddle.net/QRcF5/6/


    In the context of communication ONLY between the the parent (layout) and the child (itemView):

    1) the child triggers the custom event (opposed to vent extend Backbone.Events - it only speaks to those who have access to it = encapsulation)

    triggers: {
        'click button': 'custom_event:btn_clicked'
    }
    


    2) the parent listen to this event having access to the child with the on('show',....)

    initialize: function() {
        var that = this; // needed for the listenTo which overrides 'THIS'
    
        this.header.on('show', function(view) {
            this.listenTo(view, 'custom_event:btn_clicked', that.clicked);
        });
    },
    


    Example:

    layout = new Layout();
    $('body').append(layout.render().el);
    layout.header.show(new Header()); // Here we get access to child and its events
    


    The (hidden) power of Marionette. (I mean when I say hidden, because being relatively new, the documentation is barebone and the complex examples are scarce).

    With little perseverance anything can be accomplished.