I have extend this function inside Backbone.view
toggle: function () {
var sempurna = _.after(array_obj.length, this.render);
_.each(array_obj, function (v,k) {
v.perormSomething();
delete array_obj[key];
sempurna();
}, this);
}
And so I thought that I could render the view straight away the loop is completed. But somehow the this keyword is refering to window instead of the view. How do I point to the intended this to view.
The this is set to window because your are calling sempurna() without the dot notation (so without any explicit receiving object).
To fix this you need to _.bind (or use the browser native bind if available) your sempurna to this:
toggle: function () {
var sempurna = _.bind(_.after(array_obj.length, this.render), this);
_.each(array_obj, function (v,k) {
v.perormSomething();
delete array_obj[key];
sempurna();
}, this);
}
Demo JSFiddle.
Related
Excuse my backbone i'm not an expert, Must execute function Show absolutely and only after ResetQuestions
ResetQuestions:function () {
//Great Code Here
}),
I tried this:
initialize: function () {
this.on("Show", this.Show, this);
},
ResetQuestions:function () {
//Great Code Here
this.trigger("Show");
}),
But that was unsuccessful, does anyone know how i can accomplish this?
no need of events you can simply call the function from other function
var sampleView = Backbone.View.extend({
initialize: function () {
this.ResetQuestions();
},
Show: function () {
alert('i am at show');
},
ResetQuestions: function () {
// Execute all you code atlast call Show function as below.
this.Show();
}
});
var view = new sampleView();
var sampleView = Backbone.View.extend({
initialize: function(){
this.ResetQuestions().promise().done(function() { // Using promise here.
this.Show();
});
},
Show: function(){
},
ResetQuestions: function(){
// Execute all you code atlast call Show function as below.
}
});
Then initiate your view,
var view = new sampleView();
Hope this works!!
Perhaps you just got confused what runs what and by naming event and method with same name Show. I have created a jsfiddle with your code - http://jsfiddle.net/yuraji/aqymbeyy/ - you call ResetQuestion method, it triggers Show event, and the Show event runs Show method.
EDIT: I have updated the fiddle to demonstrate that you probably have to bind the methods to the instance, I used _.bindAll for that. If you don't do that you may get event as the context (this).
EDIT: Then, if your ResetQuestions runs asynchronous code, like an ajax request to get new questions, you will have to make sure that your Show event is triggered when the request is completed.
Is it possible for mustache lambda function to access its view instance this?
Backbone.View.extend ({
initialize: function (options) {
this.collection = options.collection // large backbone.collection
},
parseContent: function (){
return function (id, render){
//this.collection is undefined below
return this.collection.get (render (id)).get ('stuff);
}
}
});
Tried _.bind (this.parseContent, this) inside initialize (), this still carry the model context inside parseContent ().
My current workaround is saving this.collection to my app root namespace and access from there. Wondering is there a cleaner way to do this as intended above?
Appreciate your advice.
If you're going to pass around the function returned by parseContent, you should
bind that function before returning it with _.bind,
and use _.bindAll in initialize to force this in parseContent on each instance.
Your view could be written as
Backbone.View.extend ({
initialize: function (options) {
_.bindAll(this, 'parseContent');
// you don't need this.collection = options.collection
// collection is part of the special variables handled By Backbone
},
parseContent: function (){
var f = function (id, render){
console.log(this.collection);
}
return _.bind(f, this);
}
});
And a demo http://jsfiddle.net/nikoshr/VNeR8/
suppose I have a model and a view ,ths view have two method:one is bind the document mousemove event and the other is unbind method,defalut I give the document mousemove event, once the model's enable value changed I will call the view's unbind method:
window.ConfigModel = Backbone.Model.extend({
defaults: {
'enable':0
},
initialize: function(){
this.bind("change:enable", function () {
var portView2 = new PortView();
portView2.viewOff();
});
},
change:function () {
this.set('enable', 9);
}
})
window.PortView = Backbone.View.extend({
viewOn: function () {
$(document).on('mousemove', function () {
console.log('move')
})
},
viewOff: function () {
$(document).off('mousemove');
}
})
then I put an input on the document to call the model changed:
$('input').click(function () {
var configModel = new ConfigModel();
configModel.change();
})
the boot script is :
var portView1 = new PortView();
portView1.viewOn();
The problem is once I call the click the input button ,the chrome would tell me an error:Maximum call stack size exceeded it seems the change be invoke many times.So what's the problem with my problem ,how can I solve this problem
Backbone models already have a change method:
change model.change()
Manually trigger the "change" event and a "change:attribute" event for each attribute that has changed. If you've been passing {silent: true} to the set function in order to aggregate rapid changes to a model, you'll want to call model.change() when you're all finished.
Presumably something inside Backbone is trying to call configModel.change() and getting your version of change which triggers another change() call inside Backbone which runs your change which ... until the stack blows up.
You should use a different name for your change method.
That said, your code structure is somewhat bizarre. A model listening to events on itself is well and good but a model creating a view is odd:
initialize: function() {
this.bind("change:enable", function () {
var portView2 = new PortView();
portView2.viewOff();
});
}
And instantiating a view simply to call a single method and then throw it away is strange as is creating a new model just to trigger an event.
I think you probably want to have a single ConfigModel instance as part of your application state, say app.config. Then your click handler would talk to that model:
$('input').click(function () {
app.config.enable_level_9(); // or whatever your 'change' gets renamed to
});
Then you'd have some other part of your application (not necessarily a view) that listens for changes to app.config and acts appropriately:
app.viewOn = function() {
$(document).on('mousemove', function() {
console.log('move')
});
};
app.viewOff = function() {
$(document).off('mousemove');
};
app.init = function() {
app.config = new ConfigModel();
app.viewOn();
$('input').click(function () {
app.config.enable_level_9();
});
// ...
};
And then start the application with a single app.init() call:
$(function() {
app.init();
});
I'm creating a modal dialog like this
window.NewPageModalView = Backbone.View.extend({
template: _.template($('#view-template-new-page-dialog').html()),
el: $('div#main'),
events: {
'click input[type=radio]': 'newPage'
},
newPage: function (event) {
$(event.currentTarget).closest('form').submit();
},
initialize: function () { },
render: function () {
$(this.el).append(this.template());
return this;
}
});
and then I create it inside another view like this
addPage: function (event) {
event.preventDefault();
var modal = new NewPageModalView();
modal.render();
}
this works just great but what is the best way if I want to close the dialog on body click or when pressing escape?
Generally speaking when you bind events in backbone using the events hash they are delegated to the view's el, however you can still bind events to something else in the initialize method (in your case the body).
initialize: function() {
$('body').bind('click', yourfunction);
}
Edit:
As #muistooshort mentions, you will want to make sure to also unbind the event.
Inside my Backbone views, in the initialize function I do stuff like:
initialize: function () {
$(this.el).on('click', '.button', function () {
$(this).fadeTo(0.5);
}
}
This seems to go against Backbone's convention of using events. Rewriting with the events hash:
events: { 'click .button': 'fadeButton' },
fadeButton: function () {
$(this).fadeTo(0.5);
}
The problem is inside fadeButton's scope the value of this is not the same as when using .on(). What is the correct way of doing this using the events hash?
Like paul said, Backbone automatically sets the context for event callbacks to the view itself. So this in the callback will be the view instance.
So you can get the effect you intend by using the view's scoped selector function...
events: {
'click .button': 'fadeButton'
},
fadeButton: function () {
this.$('.button').fadeTo(0.5);
}
... but if you've got multiple elements with class "button" in your view, that'll fade all of them, in which case you can always use the event object that jQuery gives you to get the event target:
fadeButton: function (event) {
$(event.target).fadeTo(0.5);
}
You defined the events hash correctly.
And for every event handler defined, Backbone automatically sets the context to the view. So this within fadeButton is the view, and you will want to access the view's element.
The code below shows how you need to update the fadeButton function.
fadeButton: function () {
$(this.el).fadeTo(0.5);
}