Why should I bind on render event inside view Initialize? - backbone.js

I don't understand why should I bind on render inside view Initialize?
example:
_bindAll(this, "render") ??

You do not have to, but if your render is triggered based on an event, you will want it to run within the context of your view (this). If you have something like this:
this.model.bind("change", this.render)
The change event will be run within the context of the model, but you want the render call to run against the view.
To simplify all this binding, you can use _.bindAll and list all the methods you might call from outside your views. You should know that Backbone is auto binding the callbacks used for UI events:
events: {"click" : "render"}

Related

When should I not use a self-rendering view?

I've been studying this Backbone tutorial and came across this bit of code:
var LibraryView = Backbone.View.extend({
el:$("#books"),
initialize:function(){
this.collection = new Library(books);
this.render();
},
...
});
The author explains that this.render() makes the view render when its constructor is called.
When would you not want the view to self-render?
The render method does nothing more than adding HTML to the DOM by using jquery's html or append methods. Where you choose to call the render method on the view is an architectural choice.
Backbone is said to apply the MV* pattern where models are bound directly to the view.
As such, the view would render itself upon instantiation, and have the ability to render itself when the model changes.
However, Backbone leave a lot of decisions to the developer and is a flexible library. There is nothing that technically prevents you to use control objects that manage the flow of the views; as such, another object can instantiate and re-render the view as well.
var view = new Bb_View();
view.render();
In the end, render is just a method on the view, and you can define your own methods as well. An example reason why I would call custom methods on the view from outside the view, is when I keep reference to an array of views.
As an event occurs, I loop through the views, I might add some conditions, and then call the custom method on particular views based on the condition.

Re render a CompositeView's itemview but not it's childViews

I have a CompositeView with a collection. The CompositeView has its own model and view that is pretty complex and changes made it to its childViews need to trigger the CompositeView's view to re render but not its childViews. Is that possible?
I read in the Marionette docs "You can specify a modelView to use for the model. If you don't
specify one, it will default to the Marionette.ItemView." But nothing happens when I try to use this in my CompositeView.
Your CompositeView should listen for change event of own model and should call render on that. In this way the only ItemView associated with the composite view will re-rendered on change of own model not all childView.
this.listenTo(this.model, 'change', this.render)
You can put this line inside initialize method of CompositeView.

Marionette onShow not firing after rerender region view

I have a region, and I need to execute some code once the view is rendered. So the first time I call myRegion.show(myView)The code that goes inside onShow in myView does the work.
The same piece of code doesn't work onRender or at initialize. The problem comes, when after a change in myView I call this.render() to reflect the changes. This time, "onShow" is not firing.
I think that I can trigger an event from the view, catch it at the parent view and call again to myRegion.show(myView). But it looks like a tricky solution, and I don't know if there could be a better way to manage this situation.
onShow callback is called only once when you insert your view into the region.
I think in your case you should use onDomRefresh. Marionette calls it when view is showed into region and when it is re-rendered (but only when it is showed already). So you can make all your DOM dependent code in it.
You can read more in docs: https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.view.md#view-domrefresh--ondomrefresh-event

auto update view in backbone.js

I use backbone.js and have a model without a collection.
In the view I call fetch on the model with a callback to render the view.
this.user.fetch({success: function(d) { self.randomUserView.render() }})
how can I make the view update automatically when the model change? e.g. I don't want to specify the above callback every time I call fetch. I tried to bind the view to many model events on initialize but this did not work.
On the view, add an event handler to the view's model:
initialize: function() {
this.model.on('change',this.render,this);
}
Backbone is event-driven, not callback driven framework (although technically they are callbacks). And your approach does not seem to be native to Backbone. When you do fetch(), user model will automatically trigger "add" event. All you need to do is in the corresponding view add this in initialize:
initialize: function() {
... your code...
this.model.bind('add', this.render);
}
This way you subscribe to this even only once in the view init and don't have to ever pass explicit callbacks.
Actually if you want to have a view refresh on fetch on a collection you need to bind RESET!
this.model.bind('reset', this.render, this);
Update is only fired if the current collection is edited.
ps bindAll is dangerous and lazy. (and probably going to cause you problems down the line)

Backbone click event not firing

So I have a Backbone view in which I declare it's className. I'm trying to bind a click event to that class. So something like this:
className: "question"
events:
"click .question": -> console.log("clicked")
This doesn't seem to work. It seems to be because the element isn't inside the view itself. So if I create an element within a template, I can bind to that just fine. I should be able to bind to the view itself right? Any help is appreciated. Thanks!
From the fine manual:
delegateEvents delegateEvents([events])
[...] 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. Omitting the selector causes the event to be bound to the view's root element (this.el).
So you want your events to look like this:
events:
'click': -> console.log('clicked')
Demo: http://jsfiddle.net/6W6QE/

Resources