when the add event is fired in backbonejs? - backbone.js

When does the 'add' event gets fired in a collection?
I am in a notion that when i execute something like app.mycollection.create(this.newAttributes()); the add event will be fired.
Actually i do this while initializing a view
window.app.mycollection.on('add',this.render,this)
So ideally, first there should be a post request (when i do a create) and then the get request (my render function fetches rows from backend). But in network console, i get the opposite. I first see a get request and then the post request.
This made me thought that 'add' event gets fired immediately after a call to create method without waiting for creation to be complete.
This thus fetches me old data without including the data that has just been created.
Please shed some light.

You have executed render function immediately. Try update your code:
window.app.mycollection.on('add', this.render, this)
EDIT
Take a look
Creating a model will cause an immediate "add" event to be triggered
on the collection, a "request" event as the new model is sent to the
server, as well as a "sync" event, once the server has responded with
the successful creation of the model. Pass {wait: true} if you'd like
to wait for the server before adding the new model to the collection.

Related

Show notification before and after sync action with Flux and React

I have a task - to implement notifications/alerts on react+flux. Imagine the next situation user clicks on the button. After that I'm firing an action - for example "CALCULATE_ACTION" then I catch it in the MainStore. While processing this action in the MainStore I need to show the notification for user. Let's imagine I'm calculating something in the MainStore. Before the calculation I need to show notification "calculation has started". And after the calculation show "calculation has finished". I have a NotificationComponent which takes the notification text from the NotificationStore. So to show the notification I can trigger the "SHOW_NOTIFICATION_ACTION" and pass the text of the notification to this action, so the NotificationStore will catch it and set it to its state and NotificationComponent will be rerendered and notification will appear.
The problem is that I can't fire an action while other is in process. So if I've already fired "CALCULATE_ACTION" I can't fire "SHOW_NOTIFICATION_ACTION". Of course I can catch the CALCULATE_ACTION in the NotificationStore. But then I will be able to show only one notification - If I'll wait for the MainStore then notification will be after the calculations in the MainStore, otherwise - before.
And one more question- what if I need to show notification in the middle of the calculation?
My task is a bit abstract and I have more realistic one, but a lot of context should be explained so I've simplified the task to this example.
Does anybody has any ideas?
Any help would be highly appreciated!
In a typical react-flux setup, your components listen to changes in your stores.
Your component fires an action, your stores update, and your stores emit a change. (Stores should not fire actions)
In your (abstract) case, you could set it up as follows (with 1 action resulting in 2 store changes and 2 updates):
Front-end component listens to changes from BOTH NotificationStore as
well as MainStore.
This component fires a CALCULATE_ACTION.
NotificationStore listens to CALCULATE_ACTION. It immediately emits a
change. (without waiting for MainStore).
Front-end component receives this change event, and it retrieves some active_state
from NotificationStore (which in turn should probably read from
MainStore to determine active_state). You can have your component show this calculation busy' message.
Meanwhile, MainStore also received the
CALCULATE_ACTION. It starts the calculation, and as soon as it is
done, have it emit a change. Your component listens to this change
also, and will again retrieve the active_state from the
NotificationStore. Which is now abviously 'done' or something
similar.

Backbone listenTo timeout

I am connected to a web socket and constantly updating my model based on the incoming JSON objects.
Using this coffeesScript code:
#listenTo #model, 'change', #render
I am listening for every moment that the model is updated and then I render that newly updated model. This works well. However, I would now like to set a timeout so that if the listener doesn't detect a model update after 30 seconds, I can call a different function and update my model with a timeout message. What is the best way set up this timeout?
I think you should add callbacks at where you send ajax requests. When you listen to a model's change event, you don't know when the request is sent.
What if you want to add features like auto-refresh? In that scenario 'change' event is listened once but there could be multiple requests that can timeout. These are separated things.

Don't call render() if the View itself updated Model via Backbone.Model.set()

In my Backbone.js project I have one Model and several Views. All Views have registered callbacks for 'change:currentTextTitle' on this model:
// 'this' stands for any of the Views here
myModel.on('change:currentTextTitle', this.render, this);
Now a user performs some action, which causes the specific View to change its "current text title" field. This specific view then calls myModel.set("currentTextField", newTextValue) which in turn triggers the 'change:currentTextTitle' event calling all Views (including the one from which set() originated). Then all Views call their render callback functions.
The problem is that the render method is also called on the View from which the set()-Method was originally called, which is completely unnecessary because it is already up-to-date with currentTextTitle.
How would my Views call myModel.set() in a way that the other Views' callbacks get informed, but without triggering/calling the "source View" itself?
One workaround seems to be to pass the source view as part of the options parameter of the set() method (which gets passed along to trigger() and then along the the render() callback):
myModel.set("currentTextField", newTextValue, thisViewSetAttribute)
Then in the render callback one could check if thisViewSetAttribute != this. However, instead of implementing checks in every callback, I think it would make more sense to handle this in the Model itself by only calling the necessary callbacks and ignoring the source View from which the set() method call originated. Is this possible?
I think the 'proper' MCV solution is that your views should not know or care how the model changed, they should simply handle the change and update accordingly. If they are already current, the user shouldn't know the difference.
I definitely would not pass the source view to the model. Instead when the model changes, you could just have the view check if it is current and not re-render. But if the extra render doesn't cause any issues then just let it happen :)
In Backbone, the 'view' is both view and controller. So try to treat the change as 2 separate steps. First, convert user input into changes on the model, then as a separate step (initiated by model change event), handle that change and update the view. If each view does this, no matter how the model changes, everything will stay up-to-date.

Backbone "success" callback vs. model "change" event binding purposes

What is the purpose of the "success" callback when fetching data for a model vs. the purpose of binding to a method for the "change" event?
"success" callback
this.model.fetch({
url: '...'.
success: function(response) {
...
}
});
vs. model "change" binding
this.model.bind("change", this.attributesChanged);
Usually i use fetch-success callback in cases when i call fetch outside of the model itself and want an additional success function callback triggered in the model.
Also on a note, be careful with CRUD events though, as "change" events may still be trigger even when its unsuccessful in storing to the server, remember "change" is triggered when the model is changed. As of version 0.9.0, a "sync" event has been added to address this issue. This triggers whenever a model's state has been successfully synced with the server.
The main reason to use "success" or "error" for that matter, is to execute functionality based upon the response as "change" will only fire on successful change of the model. If your fetch failed for some reason, "change" won't fire. The callbacks allow you a bit finer level of control. That said, it kind of boils down to personal preference as to when you want to respond to the response. My thought is that if I am only interested in doing something in response to a successful CRUD operation, then listening for "change" is entirely appropriate, as I will just ignore errors.
The 'change' event will fire if the model is updated by any method, for example user input into a form which is used to change a model attribute, or fetching data from the server.
The success callback on fetch is obviously called only after fetching from the server.
So if you only want to respond to changes to the model caused by fetches, rather than 'bidirectional' changes, use a success handler rather than a change event.

LoadableDetachableModel and an Ajax button (Wicket)

I have a problem similar to the one described by LutherBaker here, i.e. the load method of LoadableDetachableModel is called before the onSubmit() method of the Ajax button. Is there a model that works similar to LoadableDetachableModel but is called after the onSubmit method?
My problem: When a form is submitted, I update a record in the database. However, this update is not visible in a drop down list (that is refreshed after the onSubmit() call - it's added to target) with a LoadableDetachableModel, because this LDM is loaded before onSubmit() method of the form.
How do I make the changes done in the onSubmit() method visible in the drop down list?
Does it work with a non detachable model? Does the component have the markup id rendered out?
A LoadableDetachableModel has a cache, to avoid extra database requests and such.
If the LDM is loaded (it's load() method being called) after the onSubmit event is triggered but before you update the record, then you need to reload you LDM by detaching it, so that it will be reloaded with fresh data when the ajax target is rendered.
So try to call detach() on the model, at the end of the onSubmit() method.
If this doesn't work, then also verify that your database commands are send at the expected moment. For example, if you use some JPA flushmodes, then some database commands may be delayed to the end of the transaction, which can cause the data to be reloaded using a read query before the update query has taken place.

Resources