Marionette onShow not firing after rerender region view - backbone.js

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

Related

Why should you put custom event listeners under intitalize in backbone?

I'm wondering why you need to put a object.on(event, callback, [context]) specifically within an initialize method in backbone, and not somewhere else?
Is it because the initialize method runs automatically -> and the listener starts to listen automatically for that reason?
A better way to design a backbone application is to separate data loading code and views construction.
This can be done by using a separate controller(A custom javascript object) that does the data load part i.e, initializing your models or collections. The controller loads the data (models/collections) necessary for a particular view.
The view instance is then created. Data required for the view can be passed as parameters to the view. One of the better ways is to pass it to use the initialize method which gets invoked automatically during the instantiation of the view.
Also we will expect the view to reflect the changes that model/collection undergoes. Its good to define what events of the model/collection that must be listened to in the intialize method since:
You know that it will be called for sure.
You know for sure that the event binding will be set, since you can reach a view from more than one way like thru a route or a click event on tabs for instance (though better designing is that you have a center piece of code which handles all the ways you reach a view).
Also set the rules for event bindings during the initialization itself.
You can also refer to the below link that talks about decoupling view from data loading.
Should the backbone router or view handle fetching data and displaying loading status?

Backbone render the view once the dom loaded to avoid div jumping

Adding the view to dom id main-wrapper one router calls the view.Page loads one by one because of the sub view added in within main-wrapper. Need to know something similar to smooth loading the dom with fade in effect or shows the page once the dom is loaded.
Another approach you can take is hold off on adding the view to the main-wrapper until all subviews are created. Create a document fragment (default behavior if "el" is not defined). Once your view and its descendent views are all created in document fragment, then add it to the main-wrapper div. This way all of your content are shown at the same time instead of one view at a time.
Either use jQuery's onReady event or the native window.onload event. In both cases you register a callback function that then kicks of the initialization of the respective Backbone views.

How can I trigger two events with a "double" action?

I've got a view Foo, with an input field, and a wrapper view Bar, with a button.
When I write something in the input and then press the button, the 'change' event on Foo's model should be triggered, and then the 'click' button on Bar's, yet only the first do happen. Is there a way to trigger both, preferably at the correct order?
Thanks!
To reiterate, and confirm your question/setup. Based on your question, this is the setup you have. You want to change the Foo.model THEN trigger the click event on the Bar.
<div id="Bar">
<div id="Foo">
<input type="text">
</div>
<button id="barButton">Update</button>
</div>
It's a little bit of an odd setup. #alexanderb illustrates it the way I also think of the whole problem but I'll explain what I'd do in your scenario assuming you know something I don't about the context of the situation! :-)
If you want the change to be triggered on the Foo.model followed by the click event on the Bar button, all you need to do manually trigger the button click from your Foo view. To do this, you can do it one of several ways. The first is to directly trigger the event of your parent (Bar) view.
// When you create your Foo subview, you pass in the parent view so you can access it
var foo = new Foo({
'parent': this // this = the barView assuming you're creating FooView inside BarView
});
// In Foo after you set your model attribute, you access the parentView
this.options.parent.$el.find('#barButton').click(); // Manually trigger the click event
// or
this.options.parent.onButtonClick() // Manually run the event handler bypassing the event
This satisfies your request to have the change event followed by the button click event in the DOM context you provided. (Not sure why in this case but I can imagine some scenarios where something similar might be desired.)
The second way of doing it is to use an event aggregator pattern which allows your views to send and receive events to one another. In this scenario, what happens is your Foo view, after updating the model triggers an event that is listened to by your parent Bar view, upon which it executes some handler.
You can read more about event aggregator pattern in Backbone here:
Event Aggregator Explanation
To be honest, I really think that alexanderb's answer is the best one for this situation unless there is something more we don't know about your special setup. But, I hope you can see and compare the two and get an idea of when and why one setup might be appropriate given a particular context.
Hm, I'm a little confused. If you don't use any backbone plugis, the workflow is different.
If you press something on a screen, an event occures on view, not in model. You have to listen to that event and update the model accordingly. If you set new value in model, change model event will occur.
Say, you have a view Foo it's subview Bar and model Boo. Both views are using the same model objects.
In Bar view,
events: {
'click .button': 'onButtonClicked';
}
onButtonClicked: function () {
var value = this.$el('.input').val();
this.model.set({ someValue: value});
}
In Foo view, you can listen for model changes
initialize: function () {
this.model.on('change:someValue', this.onSomeValueChanged);
}
In this.onSomeValueChanged you can do, what ever you like.

Why should I bind on render event inside view Initialize?

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"}

What is the point/utility of addEvents? When would it be useful?

I saw that it adds events to an Observable. However, you would only add it if you would fire it at some point. So, if you add the firing of the event at some line in your code, it was useless to put it into addEvents in the first place and when you don't place the fireEvent in your code then it was pointless to include it in addEvents. What am I missing?
If you are adding custom events with your component then you must add the events with addEvent before you can fire the events with fireEvent. Adding and firing events is useful in binding custom components together without explicitly referencing them.

Resources