I've got a view which contains several textarea components. The question is how to unbind 'click' event from the textarea that was clicked? Only from the particular one.
var StreamView = Backbone.View.extend({
el: "#stream",
events: {
"click textarea" : "addSendCommentButton"
},
addSendCommentButton : function(event) {
this.undelegateEvents();
}
});
If you want to unbind only a specific event you can use something like this:
addSendCommentButton : function(event) {
this.$el.off('click.delegateEvents' + this.cid, 'textarea');
}
Backbone attach the events using the jQuery on with a specific namespace delegateEvents plus the cid.
I am afraid that this also unbinds the events from other textareas. This is so because the off method needs the same selector that the passed to on as the jQuery documentation says:
To remove specific delegated event handlers, provide a selector
argument. The selector string must exactly match the one passed to
.on() when the event handler was attached.
Suggestion
You can have a similar behaviour changing a little your code:
var StreamView = Backbone.View.extend({
el: "#stream",
events: {
"click textarea.unfinished" : "addSendCommentButton"
},
addSendCommentButton : function(event) {
$(event.target).removeClass("unfinished");
}
});
Use a more specific selector to attach the event and remove that class when the callback is called.
YD1m answer is correct but I want to share with you another way how to do this.
If you want implement one-time event you can use one jQuery method.
You can do this in two ways:
By overriding delegateEvents method
By attaching event after rendering - this.$('textarea').one('click', _.bind(this. addSendCommentButton, this))
Check this:
var StreamView = Backbone.View.extend({
el: "#stream",
events: {
"click textarea" : "addSendCommentButton"
},
addSendCommentButton : function(e) {
e.target.removeEventListener('click', 'addSendCommentButton');
}
});
Related
i want to call a method from view#1 which is already implemented in different view (view#2)..
how to achieve this in a nice n simple way.. using backbonejs.
App.Views.view1 = Backbone.View.extend({
events: {
'click .someclass1' : 'custom_method_1',
},
custom_method_1:function(e){
//now this method calls another method which is implemented in different view
custom_method_2();
},
});
App.Views.view2 = Backbone.View.extend({
events: {
'click .someclass2' : 'custom_method_2',
},
//// this method needs to be called from view1 also
custom_method_2:function(e){
},
});
If you search how to use the eventbus, you can do it like this:
// you can name the event 'custom_method_2' as you want
Backbone.Events.on('custom_method_2', App.Views.view2.custom_method_2);
Now you are listening to the event custom_method_2 on the Object Backbone.Events that you can consider as your eventsbus.
Then in view1:
custom_method_1:function(e){
//now this method calls another method which is implemented in different view
// custom_method_2();
Backbone.Events.trigger('custom_method_2', e);
},
So I'm trying to learn how to use the backbone events using the documentation
but I'm stuck at the events part, when I click on the page class content it should alert "page tag has been clicked" but it throws an error on the commented line.
<body>
<div class="page"></div>
</body>
<script type="text/javascript">
var View = Backbone.View.extend({
initialize: function()
{
this.render();
},
render: function()
{
this.$el.html('Click me im an element');
},
events: function()
{
//Uncaught SyntaxError: Unexpected token :
"click .page" : "callme"
},
callme: function()
{
alert('page tag has been clicked');
}
});
var view = new View({
el: '.page'
});
</script>
Your events property must be either a hash
events: {
"click .page" : "callme"
}
or a function that returns a hash
events: function() {
return {
"click .page" : "callme"
};
}
You indicate a .page selector but that's your view element. Either use a global selector
events: {
"click " : "callme"
}
or set your el to an ancestor node, for example
var view = new View({
el: 'body'
});
The events is actually just an object it isn't a function. It'll work with the code below. Hope that helps.
events: {
"click .page" : "callme"
}
The other error you have is that you're not actually using the Backbone view.
You create the View correctly but you're not appending it to the view as far as I can tell.
You'd need to do something like.
$('body').html(view.render().el);
That will append your view to the DOM and add all of the event listeners.
Also instead of passing in the el to the BackboneView you could just add the class of page onto the View. Example below.
className: page,
You actually have two problems with your code, the first is that you are using a function for our events hash without returning an object (using a function is fine, but you need to return an object, or bind directly to the events hash). The second is that your are listing for an event for a child element with the page class, which doesn't exist. You want to either remove the class from where you are binding to the event and just listen to a click anywhere in your view, or listen to an existing element.
For example
var View = Backbone.View.extend({
initialize: function()
{
this.render();
},
render: function()
{
this.$el.html('Click me im an element');
},
events: {
"click" : "callme"
},
callme: function()
{
alert('page tag has been clicked');
}
});
var view = new View({
el: '.page'
});
http://jsbin.com/temicema/1/
That should be enough to get your code working, however it is probably worth understanding how backbone events work. When you specify an event in backbone that event is bound to the root el and and then listens to the events you specify matching the selector you specified. Under the hood backbone is basically using jQuery's .on to delegate the events, so in your case backbone is basically doing this.$el.on('click, '.page', this.callme).
I am a newbee to backbone.I have a view called AbcView
abc.js
var AbcView = Backbone.View.extend({
events: {
"click" : "display",
},
display: function(e){
console.log("hello");
alert("click function");
}
});
Now I am passing this abc.js to another xyz.js file and calling it in another view using ListenTo.
xyz.js
var xyzView = Backbone.View.extend({
initialize: function(){
var AbcView = new AbcView ();
this.lisenTo(AbcView, "click",this.display);
},
render: function(){
var html = this.template(AbcView);
this.$el.html(html);
return this;
},
display: function(e){
console.log("parent hello");
alert("parent display function");
}
});
With abc.js click event is triggering fine. But with xyz.js click event is not triggering.
Is this the correct way to call listenTo.
DOM events aren't delegated on the View object.
If you want to emulate this though, you'd have to manually emit the event in ABC display method:
display: function(e){
// Trigger manually
this.trigger("click");
// Your usual code
console.log("hello");
alert("click function");
}
In term of best practice, I'd probably rename "click" to a more descriptive event name.
Backbone's on and listenTo are intended for listening to events on Backbone Models and Collections.
http://backbonejs.org/#Events-catalog
This is an important thing to understand. It is not the same as UI event binding, as described in http://backbonejs.org/#View-delegateEvents.
That being said, you can use something like what Simon suggests to intermingle the two.
in my project i am not able to trigger click event registered in one backbone view from another backbone view. its actually i am having a file type input placed hidden from the user and i need to trigger the file type input.
var FileView = Backbone.View.extend({
....
events : {
"click .delete-image" : "deleteFile",
}
....
});
var FilesView = Backbone.View.extend({
....
events : {
"click #attach" : "attachFile",
},
attachFile : function() {
this.fileView.trigger("click .delete-image");
}
....
});
but i tried like this the event is not get triggered. how is it possible.
the events hash attaches itself to the jquery element that represents the view, not the backbone view itself. So you would most likely have to do something like this:
attachFile : function() {
$('.delete-image', this.fileView.$el).trigger("click");
}
but I would discourage this kind of non-pattern and instead work towards using something we call an Event Aggregation pattern. You can find a collection of really good SO solutions next:
fire an event from one view to another in backbone
Backbone.js global events
Multiple view on same page with backbone.js
I am using Backbone and I have a view with events defined:
....
events: {
'click .search-button': 'setModelTerm',
'change .source-select': 'setModelSourceId',
'change .source-select': 'activateSource'
},
....
I would like to trigger two methods when the event change .source-select fires. The problem is that the last entry in the event object overrides the preceding entry.
How can I trigger two methods in one event?
(I am trying to prevent writing another method that calls those two methods)
You can pass a wrapper function in your hash of events to call your two methods.
From http://backbonejs.org/#View-delegateEvents
Events are written in the format {"event selector": "callback"}. The
callback may be either the name of a method on the view, or a direct
function body.
Try
events: {
'click .search-button': 'setModelTerm',
'change .source-select': function(e) {
this.setModelSourceId(e);
this.activateSource(e);
}
},
The only thing that is keeping you from adding the same event/selector pair is that events is a hash - jQuery can handle multiple bindings to the same element/event pair. Good news though, jQuery events allow you to namespace events by adding a .myNamespace suffix. Practically speaking, this produces the same results but you can generate many different keys.
var MyView = Backbone.View.extend({
events: {
'click.a .foo': 'doSomething',
'click.b .foo': 'doSomethingElse'
'click.c .foo': 'doAnotherThing', // you can choose any namespace as they are pretty much transparent.
},
doSomething: function() {
// ...
},
doSomethingElse: function() {
// ...
},
doAnotherThing: function() {
// ...
},
});
The events hash in your view is just a convenience "DSL" of sorts. Just bind your 2nd event manually inside initialize.
events: {
'click .search-button': 'setModelTerm'
},
initialize: function () {
_.bindAll(this);
this.on('click .search-button', this.doAnotherThing);
}