Backbone events not binding to dom element - events

In one of my views I have:
events: {
'click .tab': 'doSomething',
},
then:
doSomething: function(){
...
},
This is a recurring structure in my views, but for some reason the 'doSomething' function is not being triggered by the click in this view.
When are the elements being bound to the event?
Any tips on debugging this?

link to fiddle here : http://jsfiddle.net/7xRak/
Omitting the selector causes the event to be bound to the view's root element (this.el).
if your class="tab" is views DOM element means this.el then you should bind event as
events : {
'click' : 'dosomething'
}
and for inner element in this.el like
<div class="tab">
<span class="inner"></span>
</div>
then you should bind event as,
events : {
'click' : 'dosomething'
'click .inner' : 'onInnerClick'
}
document : http://backbonejs.org/#View-delegateEvents

The delegation happens during the delegateEvents method at the end of the view constructor.
http://documentcloud.github.com/backbone/docs/backbone.html#section-144
Try manually calling this.delegateEvents() inside render before returning this. Are you futzing with this.el inside your initialize or render methods in a way that backbone isn't expecting?

Related

Laravel 9: Problem emitting event from child component to parent

In my Laravel 9 project, I have a parent component, whose template includes a child component.
template>
....
....
<div v-if=item.is_visible class="col-4">
<note-details-modal-component v-bind:is_visible=item.is_visible :note_id= item.id>
</note-details-modal-component>
</div>
On clicking a button in the parent component, I set is_visible to true that renders the child component through v-if. In the child component, when I press a button, it calls a method that emits an event to the parent.
closeNow: function() {
console.log('closeNow');
// this.$parent.$emit('close_note',false);
this.$emit('close_note',false);
} ,
In the parent component, I have a method.
close_note(value)
{
console.log('In parent');
this.is_visible = ! this.is_visible;
},
When I click the close button in the child component, it calls CloseNow() in the child component, and I see that in the console.log. However, that event does not emit to the parent. I have tried all suggestions that I could find on the web. Also, I do not see any errors in the Dev console.
Could someone please tell me what's wrong in my code that is preventing the event from emitting from the child component to parent?
Thanks in advance.
The thing is that nothing refer to the emit you made. If you have this:
closeNow: function() {
console.log('closeNow');
this.$emit('close_note',false);
}
You should mention the close_note when you call the child component. It should be something like that:
<note-details-modal-component v-bind:is_visible=item.is_visible :note_id= item.id #theEmitName="theFunctionYoucall">
</note-details-modal-component>
where theEmitName is close_note and the function you call has the same name. This medium can be usefull : https://medium.com/js-dojo/component-communication-in-vue-js-ca8b591d7efa

Trying to bind a local datasource data to a listview in Kendo MVVM

I am new in Kendo MVVM. Trying to bind datasource data to a listview but it does not show the data.Tried to mix and match all available examples. Want to use the template which is not working. Here is the code sample
http://dojo.telerik.com/IwawE
Modified the dojo with the fixes
http://dojo.telerik.com/IwawE/5
Your data binding declaration is incomplete and results in javascript errors when kendo tries to instantiate the listview.
data-bind="source:gsSystem,
visible: isVisible,
events: { click: }"
Firstly, there is no 'isVisible' property on your view model so the binding will return 'undefined' resulting in the listview not being shown. Either remove that binding or add the property as part of the model, for example:
isVisible: true
Secondly, there is no function defined for the click event. Usually you would specify one such as:
events: { click: onClick }
and add the handler to the model:
onClick: function (e) {
alert("Clicked");
}
However in the case of the ListView, there is no click event available. Instead, remove the event from the ListView declaration and add it to the div within the template instead:
<script type="text/x-kendo-template" id="tmpl">
<div data-bind="events: { click: onClick }">#:text#</div>
</script>

Event not triggering in Marionette Itemview

I am trying to trigger an event in the marionette itemview (List.SendQuestion), however, I was unable to register the trigger in the controller (as seen below)
Essentially, after clicking on the 'a.send', a trigger was supposed to happen and the 'send_qn_view' should capture the event and print out the message 'triggered'. But that was not happening.
Can someone advise me what might be going wrong here?
#Dailymuses.module "SidebarModule.List", (List, App, Backbone, Marionette, $, _) ->
List.Controller =
showSidebar: ->
send_qn_view = new List.SendQuestions
collection: Onethingaday.Public.friends
send_qn_view.on "itemview:ask:user", (itemview, question) ->
console.log('triggered') #THIS IS NOT EXECUTED
class List.SendQuestion extends Marionette.ItemView
template: "sidebar/list/templates/send_question"
className: 'qn_askee'
tagName: 'li'
events:
"click a.send" : "sendQuestion"
sendQuestion: (e) ->
e.preventDefault()
debugger #this debugger was triggered
#trigger "ask:user", #model
class List.SendQuestions extends Marionette.CompositeView
template: "sidebar/list/templates/send_questions"
itemView: List.SendQuestion
itemViewContainer: "ul.friends"
Edit: Corrected my answer and updated my fiddle
Sorry about that. Your syntax for event bubbling is correct.
https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.collectionview.md#childview-event-bubbling-from-child-views
"itemview:*" event bubbling from child views
When an item view within a collection view triggers an event, that
event will bubble up through the parent collection view with
"itemview:" prepended to the event name.
That is, if a child view triggers "do:something", the parent
collection view will then trigger "itemview:do:something".
Something to note. Marionette supports view triggers. If your callback is just triggering a view event you can remove the event hash and callback and shorten your code to this:
triggers: {
"click a.send": "ask:user"
}
http://lostechies.com/derickbailey/2012/05/15/workflow-in-backbone-apps-triggering-view-events-from-dom-events/
Fiddle:
http://jsfiddle.net/FRHkt/1/
For anyone new coming to this example, with Marionette 2.x, itemview:* for children views have been replaced with childview: triggers in the parent view, and the collection and composite views have also had their parameters changed from itemView and itemViewContainer to childView and childViewContainer

jQuery .on() event doesn't work for dynamically added element

I'm making a project where a whole div with buttons is being inserted dynamically when user click a button, and inside that div there's a button, which when the user click on it, it does something else, like alerting something for example.
The problem is when i press on that button in the dynamically added div, nothing happens. The event doesn't fire at all.
I tried to add that div inside the HTML and try again, the event worked. So i guess it's because the div is dynamically added.
The added div has a class mainTaskWrapper, and the button has a class checkButton.
The event is attached using .on() at the end of script.js file below.
Here's my code :
helper_main_task.js : (that's the object that adds the div, you don't have to read it, as i think it's all about that div being dynamically added, but i'll put it in case you needed to)
var MainUtil = {
tasksArr : [],
catArr : ["all"],
add : function(){
var MTLabel = $("#mainTaskInput").val(), //task label
MTCategory = $("#mainCatInput").val(), //task category
MTPriority = $("#prioritySlider").slider("value"), //task priority
MTContents = $('<div class="wholeTask">\
<div class="mainTaskWrapper clearfix">\
<div class="mainMarker"></div>\
<label class="mainTaskLabel"></label>\
<div class="holder"></div>\
<div class="subTrigger"></div>\
<div class="checkButton"></div>\
<div class="optTrigger"></div>\
<div class="addSubButton"></div>\
<div class="mainOptions">\
<ul>\
<li id="mainInfo">Details</li>\
<li id="mainEdit">Edit</li>\
<li id="mainDelete">Delete</li>\
</ul>\
</div>\
</div>\
</div>');
this.tasksArr.push(MTLabel);
//setting label
MTContents.find(".mainTaskLabel").text(MTLabel);
//setting category
if(MTCategory == ""){
MTCategory = "uncategorized";
}
MTContents.attr('data-cat', MTCategory);
if(this.catArr.indexOf(MTCategory) == -1){
this.catArr.push(MTCategory);
$("#categories ul").append("<li>" + MTCategory +"</li>");
}
$("#mainCatInput").autocomplete("option", "source",this.catArr);
//setting priority marker color
if(MTPriority == 2){
MTContents.find(".mainMarker").css("background-color", "red");
} else if(MTPriority == 1){
MTContents.find(".mainMarker").css("background-color", "black");
} else if(MTPriority == 0){
MTContents.find(".mainMarker").css("background-color", "blue");
}
MTContents.hide();
$("#tasksWrapper").prepend(MTContents);
MTContents.slideDown(100);
$("#tasksWrapper").sortable({
axis: "y",
scroll: "true",
scrollSpeed : 10,
scrollSensitivity: 10,
handle: $(".holder")
});
}
};
script.js : (the file where the .on() function resides at the bottom)
$(function(){
$("#addMain, #mainCatInput").on('click keypress', function(evt){
if(evt.type == "click" || evt.type =="keypress"){
if((evt.type =="click" && evt.target.id == "addMain") ||
(evt.which == 13 && evt.target.id=="mainCatInput")){
MainUtil.add();
}
}
});
//Here's the event i'm talking about :
$("div.mainTaskWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
});
It does not look like div.mainTaskWrapper exist.
From the documentation (yes, it is actually bold):
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page.
[...]
By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers.
You might want to bind it to #tasksWrapper instead:
$("#tasksWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
You need to specify a selector with on (as a parameter) to make it behave like the old delegate method. If you don't do that, the event will only be linked to the elements that currenly match div.mainTaskWrapper (which do not exists yet). You need to either re-assign the event after you added the new elements, or add the event to an element that already exists, like #tasksWrapper or the document itself.
See 'Direct and delegate events' on this page.
I know this is an old post but might be useful for anyone else who comes across...
You could try:
jQuery('body')on.('DOMNodeInserted', '#yourdynamicallyaddeddiv', function () {
//Your button click event
});
Here's a quick example - https://jsfiddle.net/8b0e2auu/

backbone.js: understanding browser event handling and view removing

I'm fiddling with a view and related model that look like that:
App.Views.Addresses = App.Views.Addresses || {};
App.Views.Addresses.Address = Backbone.View.extend({
events: {
"click button#foo" : "clear"
},
initialize: function(model){
this.address = model.model;
this.address.view = this;
_.extend(this, Backbone.Events);
this.render();
},
render: function(){
... rendering stuff
},
clear: function(){
this.address.clear();
}
});
and
var Address = Backbone.Model.extend({
url: function() {
... url stuff
},
clear: function(){
this.destroy();
this.view.remove();
}
});
I'm facing two problems here. The first one:
I have a button with id="foo" in my source and would like the view to catch the 'click' event of this very button and fire the 'clear' event. Problem: This does not work.
Anyway calling 'clear' on my model by hand cleanly removes the data on the server but does not remove the view itself. Thats the second problem. Hopefully someone more experienced can enlighten me.
Thx in advance
Felix
First problem:
Your button must be inside the element rendered by the view.
backbone scope events to inner elements only
You must render your view within this.el element
backbone use that element for delegation
Second problem:
Use events to destroy your view
You should not store the view in the model. This is kind of a "no no" in MVC. Your model already emits a "remove" event when deleted. Your view should listen to it and behave accordingly.
You must remove your view element from the DOM yourself
This is not handled by backbone.
Other general comments:
Views already are extending Backbone.Events
Use this.model instead of this.address

Resources