I have a collection view, and each item view is a composite view, which also has a item view. I want to listen to the events from this last (sub-sub) item view.
View.Block = Marionette.Layout.extend({
triggers: {
'click .content': 'block:click'
}
});
View.Category = Marionette.CompositeView.extend({
itemView: View.Block
});
View.Categories = Marionette.CollectionView.extend({
itemView: View.Category
});
In my controller I only have a reference to View.Categories:
var categories_view = new View.Categories({
collection: categories
});
Is it possible to listen to click events from View.Block using Marionette's built-in view events? I tried categories_view.on('itemview:block:click') but that won't work as View.Block isn't an item view of View.Categories, but of View.Category.
You'll need to use a module- or application-level event aggregator to achieve your objective:
events: {
"click .something": "triggerEvent"
},
triggerEvent: function(e){
myApp.trigger("something:clicked", e);
}
(myApp is the instance of your Marionette application.)
Then listen for that event:
myApp.on("something:clicked", function(e){
e.preventDefault();
console.log("something was clicked");
});
Related
I have a simple application that binds to a view model using Knockout JS. It uses a foreach loop that fires the Knockout afterAdd event when a new item is added to the view model. The result is supposed to be a Kendo draggable that can be dropped on a target. For some reason I can't get the drop event on the target to fire.
JSFiddle
<button data-bind="click: $root.add">Add</button>
Drop target
var ViewModel = function () {
this.operations = ko.observableArray([]);
this.add = function () {
this.operations.push("drag");
}.bind(this);
this.bind = function () {
$(".draggable").kendoDraggable({
hint: function (e) {
$("#console").append("<li>firing hint</li>");
return e.clone();
},
});
$(".droptarget").kendoDropTarget({
drop: function (e) {
$("#console").append("<li>firing drop</li>");
}
});
};
};
ko.applyBindings(new ViewModel());
The problem is that you're instantiating the KendoDropTarget widget multiple times. If I click the Add button in your example kendoDropTarget() is invoked three times. If I add a guard against this (see http://jsfiddle.net/tj_vantoll/rk6qwsy4/1/) the drop event works as expected.
Consider the following Marionette composite View. Does anyone know wy appendHtml event does Not fire:
var TreeView = Backbone.Marionette.CompositeView.extend({
template: "#node-template",
tagName: "ul",
initialize: function(){
this.collection = this.model.nodes;
},
appendHtml: function(collectionView, itemView){
alert('appendHtml triggered');
collectionView.$("li:first").append(itemView.el);
}
});
look at the alert('appendHtml triggered'); Why does it not fire?
Has that been removed?
Look at the docs. Depending on the version of Marionette you are using. Use attachHtml()
I'm having some trouble understanding how event dispatching and binding to events between children parents work in the awesomeness that is Marionette.
Is it correct that I can trigger a custom event from an itemView like this:
var Item = Marionette.ItemView.extend({
events: {
"click .foo": "do:something"
}
});
var itemCollection = Marionette.CollectionView.extend({
itemView: item,
initialize: function () {
this.on("itemview:do:something", this.onSomething, this);
}
}};
Is there some shortcut to binding to the itemView events like I would DOM events:
var itemCollection = Marionette.CollectionView.extend({
itemView: item,
itemviewevents: {
"itemview:do:something": "onSomething"
}
}};
Thanks :).
You're confusing triggers and events. Your code should be
var Item = Marionette.ItemView.extend({
triggers: {
"click .foo": "do:something"
}
});
Use the events hash to have a function called when an event takes place, use the triggers hash to have a trigger executed.
I searched info on this topic but found only info about getting event element.
Yes, I can get an element of clicked div, but why it's fired all 19 times? (it's the number of views total). Info of clicked event is same - of the clicked div.
Here is what divs look like: http://d.pr/i/AbJP
Here is console.log: http://d.pr/i/zncs
Here is the code of index.js
$(function () {
var Table = new Backbone.Collection;
var TrModel = Backbone.Model.extend({
defaults: {
id: '0',
name: 'defaultName'
},
initialize: function () {
this.view = new Tr({model: this, collection: Table});
this.on('destroy', function () {
this.view.remove();
})
}
});
var Tr = Backbone.View.extend({
el: $('.pop-tags').find('.container'),
template: _.template($('#td_template').html()),
events: {
'click .tag': 'clicked'
},
clicked: function (event) {
event.preventDefault();
event.stopPropagation();
console.log(event.currentTarget);
},
initialize: function () {
this.render();
},
render: function () {
this.$el.append(this.template(this.model.attributes));
return this;
}
});
for (var i = 0, size = 19; i < size; i++) {
var trModel = new TrModel({id: i, name: 'name_' + i});
Table.add(trModel);
}
});
How can I avoid all elements from firing an event and fire only one that clicked and only 1 time?
el: $('.pop-tags').find('.container'),
Don't do that. You are attaching every view instance to the same DOM node. Each backbone view needs a distinct DOM node or, as you see, delegate events become complete chaos. In your view, set tagName: 'tr', then when creating your views, create them, call .render() and then append them to the DOM with something like $('.table-where-views-go').append(trView.el);.
You also may want to brush up on the basic MVC concept because Tables and Rows are view-related notions, not model-related, so a class called TrModel is a code smell that you aren't clear on Model vs View.
I would use a slightly different approach to solve your problem.
Instead for one view for every tr I would create one view for the entire table.
When I create the view I would pass the collection containing the 19 models to the view and in view.initialize use the collection to render the rows.
I created a jsbin with a working example.
I have a kendo treeview i use this function to bind event change
change: function (e) {
if (e.field == "checked") {
gatherStates(e.items);
alert(e.items);
}
}
If i want to know the 'dad node'(the node that contain the selected child) of the selected child?
You can get the parent node from e.node:
tree.dataSource.bind("change", function (e) {
if (e.field == "checked") {
var node = e.items[0];
console.log("node", node.text);
console.log("parent", e.node.text);
}
});
Example here (http://jsfiddle.net/OnaBai/ECnef/)
i have a same kind of issue with kendo treeview checkboxes in IE8
jQuery("#treeview").kendoTreeView({
dataSource: ss,
dataTextField: ["ss_"],
checkboxes: {
checkChildren: true
},
select: function (e) {
jQuery(e.node).find("input")[0].click();
}
});
var treeview = jQuery("#treeview").data("kendoTreeView");
treeview.expand(".k-item");
treeview.dataSource.bind("change", onCheckboxClicked);
selecting the text of checkbox fires the select event of treeview and in this event i click the checkbox manually (my requirements)...which in turn fires change event of data source in IE-9. But it doesn't fire the change event of datasource in IE-8. What is the issue?
Thanks