Reputation: 1603
So this is the code on the ParentView: relevant method:
openChildView: function(){
var childView = new ChildView({
container: $container //container where the child map should be appended
});
childView.show();
}
this is the code of the ChildView:
ChildView = Marionette.ItemView.extend({
template: _.template($(templates_c).filter('#my_child_view_template').html()),
ui: {
saveButton: 'button.js-save',
uploadButton: 'button.js-upload',
deleteButton: 'button.js-discard'
},
events: {
'click @ui.saveButton': function() {
log.debug('save');
},
'click @ui.uploadButton': function() {
log.debug('upload');
},
'click @ui.deleteButton': function() {
log.debug('delete');
}
},
show: function() {
this.render();
},
initialize: function(){
this.container = this.options.container;
this.id = this.options.id;
},
remove: function(){
// Don't know yet if this is the proper way, but for now it works
this.container.find('.container-child-view').remove();
},
render: function(){
this.container.append(this.template({
id: this.id,
img: '...'
}));
log.debug('on render');
this.bindUIElements();
this.delegateEvents();
return this;
}
});
this is the code of the template of the ChildView:
<script type="text/x-template" id="my_child_view_template">
<div class="block container-child-view">
<div class="block-title">
<h4><%= id %></h4>
</div>
<div class="img">
<img src="<%= imgUrl %>">
</div>
<div class="row text-center">
<div class="btn-group btn-group-xs">
<button id="discard" type="button" class="js-discard btn btn-alt btn-warning"><i class="fa fa-times-circle"></i> Cancel</button>
<button id="upload" type="button" class="js-upload btn btn-alt btn-primary"><i class="fa fa-upload"></i> Upload</button>
<button id="save" type="button" class="js-save btn btn-alt btn-primary"><i class="fa fa-save"></i> Save</button>
</div>
</div>
</div>
</script>
The childView is being rendered on top of the parentview but no events are triggered on it (save, discard, upload).
Any hints/ideas?
Thanks.
Upvotes: 0
Views: 136
Reputation: 5053
The way .delegateEvents()
binds events is by delegating to the view's el
. In the source you'd see this:
delegate: function(eventName, selector, listener) {
this.$el.on(eventName + '.delegateEvents' + this.cid, selector, listener);
},
As you can see the jQuery .on()
is invoked on the view's $el
. If a selector
argument is passed to .delegate()
(like, say .js-save
) that selector's events are delegated to its containing view's el
.
The way you override .render()
you chose to substitute the "all-mighty" this.el
for this.container
. Invoking this.delegateElements()
still calls .delegate()
to do the binding on this.el
, while your view actually lives in this.container
. The view events are bubbling up to an unbound container.
A quick fix may be to override render like this:
render: function(){
this.container.append(this.template({
id: this.id,
img: '...'
}));
log.debug('on render');
this.bindUIElements();
// .setElement is an internal method that will
// make your container the view's el and will call
// .delegateEvents on this new el
this.setElement();
return this;
}
});
I probably can't call myself an upright Marionette community denizen unless I also provided you a more framework-oriented solution. It looks to me that you've overriden .render
because you want to 1. render the ItemView
into a specific containing element and 2. you want to load non-model data into your template.
el
Backbone will take an existing DOM element for a view's el
. Just pass in a selector or a jQuery object on the view's instantiation,
var childView = new ChildView({ el: $container });
The Marionette .render()
method will attach the view to that $container
.
Marionette has this handy view utility, templateHelpers
, that lets you put data in the scope of the template renderer. The data can be any JS object, including functions. Just include the property in your view.
templateHelpers: function () {
return {
img: function(){
return 'http://some-domain.com/img/" + this.id;
},
id: this.id
};
}
});
where, in this version of the templateHelper
this
is the context of the view.
Upvotes: 1