Backbone event bus, making sure each event is processed only once - backbone.js

I'm building a project using the Backbone global as an event bus. The idea is that a view will trigger a custom event and pass in some data, then whatever collection is listening for that event will use the data to create a model and add that model to itself, and give some kind of message.
I notice that if I start from a new instance of my application and trigger one of these events, then in Chrome Dev Tools, Backbone._events looks something like this: {'add_person': [Object] } and the appropriate event handler runs and processes that one object in the value array. So far, so good.
Now, let's say I trigger that event handler again. What I've noticed is that Backbone._events looks like {'add_person': [Object, Object]} and the event handler runs twice, presumably on both members of the value array, including the first which was already processed.
My question is how do I prevent this behavior, short of binding the event with once and re-binding it after each time it's called? Thanks.

I'm not entirely sure what your setup is, i.e. how you're triggering and listening to these events you're firing but it sounds like you might be doing something like:
GlobalEventBus.on('add_person', this.addPerson, this);
Assuming you're binding to the event using on this could well be your problem if you're not manually unbinding the listener when your view is destroyed.
You're better off using Backbone's listenTo when listening to events that are triggered from an object outside the object you're listening in.
So, for example, in your collection you'd instead have:
this.listenTo(GlobalEventBus, 'add_person', this.addPerson)
Again though, i'm not entirely sure what your setup is.
See this codepen for a working example.
Only one events is triggered each time but keep in mind that only one model is being added because each model is a duplicate and has the same id. Assuming each model was unique it would be added to the collection.
Some further info on listenTo

Related

how to call the method in another viewmodel using event aggregator in wpf

I have two Views and two ViewModels with names Part and partItem. I have one private method in PartViewModel and I just need to call that method from PartitemViewModel with EventAggregator.
Either move the method in a service available to both view models or create an event and subscribe to it in PartViewModel and publish it from PartItemViewModel.
The event variant has the drawback that you cannot easily return anything. Also consider that if you have multiple instances of PartViewModel, all of them will react to the event.
You seem to have misunderstood what an event aggregator is all about: Loose coupling between the publisher and the subscriber.
You don't ever call a method of another view model using an event aggregator.
The publisher publishes an event and don't know anything about any of the subscribers that may have subscribed to receive messages of the same type.
The publisher and the subscriber only knows about the event aggregator but they don't know anything about each other. That's the whole point of using an event aggregator in the first place.
Please refer to the following link for more information: https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

Backbone listening to collection sync event in my View [duplicate]

What are the advantages and disadvantages of the following 2 lines of code? I don't understand why there are 2 different ways to do the same thing.
this.listenTo(app.Todos, 'change:completed', this.filterOne);
app.Todos.on('change:completed', this.filterOne);
Also when using .on, how do I determine is the default context?
listenTo is the newer and better option because these listeners will be automatically removed for you during stopListening which is called when a view gets removed (via remove()). Prior to listenTo there was a really insidious problem with phantom views hanging around forever (leaking memory and causing misbehavior) because view methods were referenced as event listeners on models even though the view instances themselves were long gone and no longer in the DOM.
If you want to read the back story for listenTo, search the backbone github repository for listenTo and read through some of the longer issue discussions.
As to the default context, several things can end up bound to this:
if you do the binding via this.listenTo, it will always be the view instance (pointed out by Wim Leers in the comments)
without this.listenTo, the story gets complicated
For misc events, it will be the global object (best to avoid this)
for DOM events, it will be the source element just like in regular DOM event binding
If you provide an explicit context (the 3rd argument to foo.on), backbone will use that (thus this is a more robust approach)
If you use the ECMA standard function () {//your event handler}.bind(this), you can also manually control the context (also recommended)
As #mu pointed out, _.bind or $.proxy are available alternatives to ECMA function.bind
For backbone views, doing this.bindAll('onClick', ...) will ensure the view instance is the this context when any view methods are used as event handlers
any events wired up by using the view's standard events property will get bound for you automatically to the view instance by backbone (this is belt & suspenders with bindAll)
So to summarize into some guidelines:
use the events property whenever possible as it is concise and correct
use this.listenTo for all bindings to models and collections
any additional bindings remember to bind the context reliably using your preferred method. I usually use ECMA Function.bind because hey, standards, but there are several good options here.
With listenTo, the object whose events you want to listen to is passed as the first argument. In the case of on, it is actually a method on that object.
The advantages of listenTo over on are:
The listener keeps track of all the event handlers, making it easier to remove them all at once when needed.
The callback’s context is always set to the listener itself.

Google realtime API OBJECT_CHANGED event fired by (almost) anything happening?

Take a custom realtime object "MyObject" one property of which is an IndexReference referring to a CollaborativeList "MyList". "MyObject" also has a collaborative field property "MyProps" into which I put a json string.
In order to detect changes to "MyProps" I tried the following:
MyObject.addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED, dealWithChanges);
However, when I make any change to an object in "MyList", which shouldn't affect the IndexReference in any way, the OBJECT_CHANGED event is fired on "MyObject"
Is this by design? It makes the OBJECT_CHANGED event useless, effectively a "something has changed somewhere" event, but without it there appears no way to detect a change to "MyProps".
Object changed events bubble, so you can listen higher up the tree for anything that is happening lower.
To listen only for changes on collaborative fields within the particular custom object, you want a ValueChangedEvent

Triggering a command in the view model based on an action in the view

I am working with the Infragistics XamDatagrid. When an event takes place in the view (new record updated), I would like to call a method in the view model. I can't just listen to the CollectionChanged event of the source in the VM because that event gets triggered once the user begins editing the new row in the grid. The RecordUpdating event gets called when the user finished the edits.
What I am doing now is accessing the DataContext directly and calling the method. The problem is that there is nowhere I can find to attach a Command to the gird that would tigger on the event I am interested, nothing like the Command of a Button.
Generally, what is the best way to call into a VM from a view when there is no Command parameter I can set in the view?
Code-behind glue is fine in most cases, but if you find yourself gluing the same type of thing repeatedly, you can look into Attached Behaviors. Here's one old-school approach the introduces the concepts, but doesn't use the new Behavior class: http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx
Here is an example using the new Behavior class, including a demonstration of how it integrates with Blend: http://geekswithblogs.net/lbugnion/archive/2009/04/05/using-a-behavior-to-magnify-your-wpf-applications.aspx

Distinguish UI change to variable from code-behind change

Like the title says I am trying to architecture into my application a way to distinguish the source of a variable change, either from UI or code-behind.
My problem is that I need to trigger some action after a property changed its value, but I only need to do this when the change comes from the UI because otherwise I don-t want to perform that action. I am having some trouble because, for example when a checkbox(two way binding), changes state, my binded property gets updated and then I use the checked and uncheked events to trigger that action.The problem is that when I change the property in codebehind it also triggers those events and I do not want that. Right now, i am using a flag that enables, or not, the actions at the event handlers but I do not feel that this is a good idea.
Any sugestions or ideas?
I am considering using only one-way binding and control everything my self, using commands.
It looks like you have some confusion between your model and your controller. There shouldn't be any cases where it matters if the a change to the model comes from the user or not. If you want to have something like a confirm message it the user makes the change, then don't bind the view control directly to the model, but have the controller respond to the event.
That way, if the control is changed to be the same as the model, then the change is internal, and no confirm is required, but if the control is changed by the user, then the control state differs from the model, and a confirm can be shown.

Resources