I'm developing a web app using Backbonejs.
I have a use case where I have to pass the new position of div1 to a double click event handler of a Backbone view.
My code looks like
var MyView = Backbone.Views.extend({
events: {
'dblclick #div1' : 'div1ClickHandler' //here I want to pass new offset for #div1
}
});
div1ClickHandler: function()
{
......
}
var myView = new MyView({model: myModel,el : #div1});
You can do that: inside div you need to add a new field with name data-yourfieldName and from js call that:
yourFunctionName: function(e) {
e.preventDefault();
var email = $(e.currentTarget).data("yourfieldName");
}
Assuming that your view element is a child element of the jquery widget, the best thing is probably to grab the values you need in the click handler:
var MyView = Backbone.Views.extend({
events: {
'dblclick #div1' : 'div1ClickHandler'
}
});
div1ClickHandler: function()
{
var $this = $(this);
var $widget = $this.parents('.widget-selector:first');
$this.offset($widget.offset());
$this.height($widget.height());
$this.width($widget.width());
}
var myView = new MyView({model: myModel,el : #div1});
If the jquery widget is always the direct parent of your view element, you can replace parents('.widget-selector:first') with parent(); otherwise, you'll need to replace .widget-selector with a selector that will work for the jquery widget.
You can pass widget in view itself, then you will have full control over widget.
var MyView = Backbone.Views.extend({
initialize: function(options) {
this.widget = options.widget; // You will get widget here which you passed at the time of view creation
}
events: {
'dblclick #div1' : 'div1ClickHandler' //here I want to pass new offset for #div1
}
});
div1ClickHandler: function() {
// Query to fetch new position and dimensions using widget
// update the respective element
}
var myView = new MyView({model: myModel, el: $('#div1'), widget: widgetInstance});
Related
I'm having an issue when I am trying to switch the view after a model save on a click event.
The flow I am trying to create is a reorder process, the user will have a confirmation page to reorder. On clicking submit an api call will execute and the invoice page will load on success.
Currently when I click the submit button the first time nothing happens and when i click again I can get an invoice page. no such issue for the cancel button.
var confirmView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
var template = _.template( $("#confirmReorder_template").html());
this.$el.html(template);
},
events: {
"click #submitButton": "submitReorder",
"click #cancelButton": "cancelReorder"
},
submitReorder: function(event){
var URI='<config property="api.url.itemReorder"/>';
var ItemReorderModel = new itemReorderModel({url:URI});
$("#submitButton").click(function(event) {
event.preventDefault();
ItemReorderModel.set('id','1');
ItemReorderModel.save( {}, {
success : function() {
var response = ItemReorderModel.toJSON();
var InvoiceView = new invoiceView({el: $("#itemData")});
},
error : function(model, xhr, options) {
}
});
});
},
cancelReorder: function(event){
document.location.href = "items_list.ctl";
}
});
second view
var invoiceView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
var template = _.template( $("#reorderInvoice_template").html());
this.$el.html(template);
},
events: {
"click #returnButton": "itemlist",
"click #printButton": "print"
},
itemlist: function(event){
document.location.href = "items_list.ctl";
},
print: function(event){
}
});
loading of first view
$(document).ready(function() {
var ConfirmView = new confirmView({el:$('#itemData')});
});
I'm new to backbone so not sure if I should be using a route, I also have read something about binding, but still trying to get my head around how it all works.
any advice is much appreciated.
You are binding a new event handler in submitReorder method, and your actual functionality is inside that event handler.
So the fist time you click the button, the event handler delegated toview via backbone event hash will trigger submitReorder, which binds a new event handler with actual functionality directly to the button element.
Next time when you click it, this new direct handler will also trigger and fire the functionality you expect.
Each time you click the button you're adding a new event handler.
Your code should be simply:
submitReorder: function(event){
event.preventDefault();
var URI='<config property="api.url.itemReorder"/>';
//-----^------ if this is hardcoded, why not specify this in the model itself..?
var ItemReorderModel = new itemReorderModel({url:URI});
//-------------^----------- why not do this just once while initializing view..?
ItemReorderModel.set('id','1');
//-------------^----------- if this is hardcoded, why not set specify it in model..?
ItemReorderModel.save( {}, {
success : function() {
var response = ItemReorderModel.toJSON();
var InvoiceView = new invoiceView({el: $("#itemData")});
},
error : function(model, xhr, options) {
}
});
},
I also suggest initializing the model in the view's initialize method and caching it as it's property rather than initializing a new model on every click.
Good morning,
i have a mootools class with the event 'beforeunload' associate to the window object.
i need to add similar event when my partial dom container change/remove.
There is a way to intercept this event?
This is my class code:
var Push = new Class({
Implements: [Events],
attachPushClassEvents: function() {
var self = this;
window.addEvent('beforeunload', function(event){
// do something
});
},
initialize : function(domContainer) {
this.container = domContainer;
self.attachPushClassEvents();
}
});
Thanks in advance
I'm writing Todo app with Backbone.js
You can see part of my code below.
Model:
var Todo = Backbone.Model.extend({
defaults : {
title: 'Task Title',
complete: false
},
initialize: function(){
this.on("change:complete", function () {
alert("foo");
});
}
});
View:
var AppView = Backbone.View.extend({
collection: todoCollection,
el: 'body',
events: {
'click #tasks li .complete-task' : 'toggleComplete'
}
toggleComplete: function (e) {
var modelCid = $(e.target).parent('li').attr('id');
if ( this.collection.get(modelCid)['complete'] ){
this.collection.get(modelCid)['complete'] = false;
} else {
this.collection.get(modelCid)['complete'] = true;
};
}
});
But something working wrong and change event in the model doesn't working. I can't understand where I have mistakes.
Help me, please.
10q.
As per the Backbone Documentation:
Set model.set(attributes, [options])
Set a hash of attributes (one or
many) on the model. If any of the attributes change the model's state,
a "change" event will be triggered on the model. Change events for
specific attributes are also triggered, and you can bind to those as
well, for example: change:title, and change:content. You may also pass
individual keys and values.
So you need to be using the set method on the model for these events to be fired. So you would need to use something like this:
this.collection.get(modelCid).set('complete',false);
Given a panel
var panel = new Backbone.CollectionView({...})
How do I get the current model being sorted?
panel.on('sortStart', function(e) {
var index = something;
});
I suppose you use some kind of UI manipulation tool for example jQuery UI. As Lesha said in her comment it can be done through triggering of event on the model view.
//creting children view
var PanelItem = Backbone.View.extend({
events: {
"sortStart": "sortEventPropagation"
},
initialize : function (options) {
this.parentView = options.parentView;
},
sortEventPropagation: function(){
this.parentView.trigger('sort:start:propagated', this.model);
},
})
Everytime you are creating panelItem view you need to pass it panel in options as parentView.
var childView = new PanelItem({
parentView: panel
})
And on panel you could easily listenTo sort:start:propagated event
var Panel = Backbone.CollectionView.extend({
initialize: function(){
this.listenTo(this, 'sort:start:propagated', function(model){
//Do magic with model
})
},
})
The 2nd answer to this question nicely explains how event declarations in Backbone.js views are scoped to the view's el element.
It seems like a reasonable use case to want to bind an event to an element outside the scope of el, e.g. a button on a different part of the page.
What is the best way of achieving this?
there is not really a reason you would want to bind to an element outside the view,
there are other methods for that.
that element is most likely in it's own view, (if not, think about giving it a view!)
since it is in it's own view, why don't you just do the binding there, and in the callback Function,
use .trigger(); to trigger an event.
subscribe to that event in your current view, and fire the right code when the event is triggered.
take a look at this example in JSFiddle, http://jsfiddle.net/xsvUJ/2/
this is the code used:
var app = {views: {}};
app.user = Backbone.Model.extend({
defaults: { name: 'Sander' },
promptName: function(){
var newname = prompt("Please may i have your name?:");
this.set({name: newname});
}
});
app.views.user = Backbone.View.extend({
el: '#user',
initialize: function(){
_.bindAll(this, "render", "myEventCatcher", "updateName");
this.model.bind("myEvent", this.myEventCatcher);
this.model.bind("change:name", this.updateName);
this.el = $(this.el);
},
render: function () {
$('h1',this.el).html('Welcome,<span class="name"> </span>');
return this;
},
updateName: function() {
var newname = this.model.get('name');
console.log(this.el, newname);
$('span.name', this.el).text(newname);
},
myEventCatcher: function(e) {
// event is caught, now do something... lets ask the user for it's name and add it in the view...
var color = this.el.hasClass('eventHappened') ? 'black' : 'red';
alert('directly subscribed to a custom event ... changing background color to ' + color);
this.el.toggleClass('eventHappened');
}
});
app.views.sidebar = Backbone.View.extend({
el: '#sidebar',
events: {
"click #fireEvent" : "myClickHandler"
},
initialize: function(){
_.bindAll(this, "myClickHandler");
},
myClickHandler: function(e) {
window.user.trigger("myEvent");
window.user.promptName();
}
});
$(function(){
window.user = new app.user({name: "sander houttekier"});
var userView = new app.views.user({model: window.user}).render();
var sidebarView = new app.views.sidebar({});
});
Update: This answer is no longer valid/right. Please see other answers below!
Why do you want to do this?
Apart from that, you could always just bind it using regular jQuery handlers. E.g.
$("#outside-element").click(this.myViewFunction);
IIRC, Backbone.js just uses the regular jQuery handlers, so you're essentially doing the same thing, but breaking the scope :)