Subscriptions to model lifecycle events accumulate - ember.js

When updating a record, I do the following:
...
this.transaction.commit();
entry.on("didUpdate", this.afterSave.bind(this, success_msg));
But my function afterSave "accumulates" on the run loop (no better way to describe it). That is, the first time that I edit a record, afterSave is called once. The second time, it is called twice, and so on.
What am I doing wrong here?
EDIT
According to the model lifecycle, record.on subscribes to events. When I want to save en edited record, I basically do the following:
update the model data, updating some derived properties from the view
commit the transaction
suscribe to the didUpdate event, to notify the user and perform some final cleanup
So, every time that I edit the record, I suscribe to the didUpdate event. I expected that this was a one-time suscription. That is: I suscribe, the event is fired, I handle it, done and forgotten.
But maybe Ember practices are not supposed to work like this. It seems that I each time I call .on('didUpdate' the old suscription is still remembered. Is this so? I do not want to do this. How can I do one of these:
remove any existing suscriptions from the current record
or get a fresh record, so that I can suscribe to events from scratch. Currently I get the record with this.get('content')

I guess to avoid accumulation of subscriptions you should use one: http://emberjs.com/api/classes/Ember.Evented.html#method_one as a one time subscription. one subscribes a function to a named event and then cancels the subscription after the first time the event is triggered.
remove any existing subscription
As for the unsubscription, you could do it with on's counterpart off: http://emberjs.com/api/classes/Ember.Evented.html#method_off
Hope this helps.

Related

AgGrid Detect changing on columns/filters/sortings events

I'm using ag-grid and I'd like to save the layout/state of the user. Pretty much something like this
This solution forces the user to click on the button to save the preferences ("Save state"). There is some other way/event to detect that the user changed the state of the table (in order, to me to save and avoid to force the user to click on a button for that)?
I was hopping to find some method here but i didn't..
I initially had code that listened to all of the applicable events from the grid, but ultimately, I found it easier to just save the entire grid state in the component's onDestroy method, regardless of whether anything has actually changed.
Found my answer here.
All the events are here but i prefer to add a global event:
addGlobalListener(listener) Add an event listener for all event types coming from the grid.)
Source: AgGrid javascript grid api

model ready event not fired after transition to page where model is needed

10
I have a model with a bunch computed properties and things in a ready event:
one field of the model is a json field, for which I defined sub keys if non existent.
dynamic computed properties depending on the model content are defined
the model is associated to route rep/route/:idmodel with findRecord call to a backend
when I am on the page /rep/route/123, for instance, the ready event is fired and everything is ok,
so far so good
When I go elsewhere and return to /rep/route/123 the ready event is not fired again. it seems ok since there was not another ajax call, the record is in the data storage.
But what was defined in the ready callback seems not to persist. if the ready event was not called on the page /rep/route/123 I am returning on
subkeys of the json field are not there anymore
dynamic computed propertiesare not there
that is to say if the model has been loaded from the backend previously, the ready event was fired then, but the benefits of it (some computed properties defined dynamically on the model) disappear once I return on the page where it would be needed, if no new ajax call is needed.
the only workaround I found is to call model.reload on some didInsertElement of a component in the /rep/route template, to force ajax call and fire the ready event
I also tried to call this.get('model').ready() directly but it does not work.
So what would be the best way to keep all dynamic things defined in the ready event, when quitting the page and returning on it afterwards.
thanks
I am not sure I understand your question correctly, but an Ember route with a dynamic segment will only have its model hook called when it is .entered via the URL.
Since your :123 is a dynamic segment, transitionTo will not get model hook called in your route.

Child controller observers still active after route change

I'm currently working on a map application with EmberJS, using ember-leaflet for displaying the map. See this jsFiddle for my current setup:
http://jsfiddle.net/HUnnr/1/
My problem is, that I didn't get the click event delegated to the PlacesNewController, only if the /places/new route is open.
my first attempt
Delegating the click event from MapView -> PlacesController -> PlacesNewController, but that did also handle the click event and add a marker to the map, after I changed the route, because PlacesNewController was still alive.
my second attempt
Then I tried Embers Evented mixin. After I had delegated the event from MapView -> PlacesController, I triggered an event. I bind PlacesNewController to this event on PlacesNewRoute.activate and unbind it on PlacesNewRoute.deactivate. The main problem was, that I couldn't access the model of PlacesNewController from the event handling function.
Both solution above doesn't seem to be the "ember way". I think there is a better solution for something like this. Maybe someone could help me to solve this problem. I think, something like direct delegating map events to PlacesNewController would be the cleanest solution, but I didn't know how I could achieve that with Ember.
EDIT:
Here is a new jsBin:
http://emberjs.jsbin.com/uHOPOfi/23/edit
The main problem is, if you first visit /places route, as expected the observers for zoom and isCloseEnough are not called. After that you go to /places/new and the observers are working as expected. But what I didn't understand is, why after going back to /places, the observers and with them also the PlacesNewController are still active? I thought Ember
send an action to the controller.
You can bounce actions around through controllers.
(sorry, switched to jsbin, jsfiddle doesn't fit well on my screen)
http://emberjs.jsbin.com/AguxORAD/3/edit
Personally I'd ditch the new route/controller, it seems weird since all of the real logic lives in places and you'll have to proxy info back and forth, but that's up to you.
I have found a good solution for this problem with the hints from kingpin's answer and this video. The main point is, that every event from the view hits the current route. So the map always delegates the click event. But then it could be processed route depended in PlacesRoute or PlacesNewRoute. So the PlacesNewController does all the place creation logic, the PlacesController does index logic and so on. I think that's a good starting point at the moment.
Here a jsFiddle, that shows my current solution described above.
#kingpin: thank you for your help

Sending action to Ember.StateManager : is goToState mandatory?

In the documentation of Ember.StateManager it's said that : "Inside of an action method the given state should delegate goToState calls on its StateManager". Does it mean that if I send an action message, I necessarily need to transit to another state. Is it possible to stay in the same state but doing some task by sending an action ? For example, I'm in a state "loading" and I run two actions "preprocess" and "display".
Very simply: an action message may but does not have to transition to another state.
Something you didn't ask, but is related and important: it is a bad idea and bad design to call goToState in an enter or exit method.
When dealing with statecharts in general, you can do whatever you want. It's not mandatory to switch states in an event handler. A common case would be an event handler that shows a cancel/save dialog. You can easily put the dialog on the page in the event handler, and proceed accordingly depending on which button is pressed.
A separate question is should every event handler basically just go to another state. In the above scenario, you can certainly go to a "confirm" state, the state-enter method will show the dialog, and there would be two handlers, one for each button. Those handler would in turn go to other states.
Both design choices I think are equally valid, at least in that scenario. If you choose to implement a separate state for every action, you will end up with a lot of small but concise states. If you choose to do stuff in the event handlers themselves, your states will be bigger, but there will be less of them.
One thing I will say is if an event handler is getting complicated, you are probably better of with a new state. Also, be consistent.
For you specific scenario, if I'm reading it right, you want to load data and then change the display to show the data, based on an event. In this case, I would use new states.
So you press a button that starts the process
In the event handler, go to some sort of 'MyDataSection' state
Initial substate is 'loadData'
Enter state method of 'loadData' starts the loading process
Event handler 'dataLoaded' in 'loadData' to handle when the data loads; this means you need to fire an event when the data loads
'dataLoaded' event goes to the 'show' state
show state shows the view (or removes activity indicator etc) and handles any events that come from the display.
What's good here is that if you have multiple ways to get to this section of the app, all actions that lead to this section only need to go to this state, and everything will always happen the same. Also note that since the view event handlers are on the show state, if the user hits a button while the data is loading, nothing will happen.

Sitecore - Creating an New Item on the OnSavingItem Event redirects the Shell to the newly created Item

Got an annoying issue.
When a user edits a field on an item, we use a OnSavingItem event handler to create some new items elsewhere in the background as it were.
Problem is the item the users edited the field of gets redirected to the item we invisible created in the background.
We want it to stay where it is... Any ideas?
thanks
If you want to disable the transfer to the item you've just created you could also consider implementing the following code:
// Before we copy the item we put notifications on to make sure we won't be transfered to the newly created item
Sitecore.Client.Site.Notifications.Disabled = true;
// Your action comes here
Sitecore.Client.Site.Notifications.Disabled = false;
Are you using the
<event name="item:saved">
Handler? If so, don't forget that this event is fired on all the new items you create as well, potentially triggering a recursive event loop.
This answer came from the SiteCore forum ... credit goes to John West
I think you could use the item:saving event or the saveUI pipeline. Use the event if you need to handle changes that occur through APIs, or use the pipeline if you only need to handle changes that occur through the user interface.
You could also consider adding the logic to the field itself.
John West Sitecore Blog
item:saved is much heavier than a processor within the saveUI pipeline. For example, item:saved is triggered during publishing which is not what you really want. I always recommend handling such customizations either on the pipeline or workflow action level.