Ember2.8 : Refresh absolutely everything on transitionToRoute('/route') - ember.js

So I currently have a card game that when finished loads up a modal with a button to transition back to the home route. This is the action that is called when the modal's close button is clicked.
goBackHome() {
this.transitionToRoute('/games');
},
It does redirect to the requested route, but all the changes to back-end data I did still remain. I've also tried passing it the model itself
goBackHome() {
this.transitionToRoute('games');
},
Basically, it doesn't do a hard refresh of everything. What I would like is when transitionToRoute is called to reload the route as if I was inputting the exact URL into the browser myself.

Well I try to write possible way to do this, hope you can pick one and solve your problem.
you need to add this.refresh(); to either your method or in model() to force reload the model to get new data (depends on what you need)! if you want to reload the location the whole windows I mean just add location.reload();
one example should be
model(id){
var post = this.get('store').find('post', id); // Find the post from the store
post.reload(); // Force a reload
return post; // Return the fetched post NOW and the information will be updated.
}
Moreover, you can do something else in your model() look at the example :
model(params) {
return this.store.findRecord('whatever', params.id, { reload: true });
}
this { reload: true } enforces the model to get fresh data, it can be implemented with findAll as well.
ref: At the moment I'm just using the afterModel hook to force a reload, but it would be good to get the reload flag working again.
so, you can do also another way which is you can send a param to the function and get that in route and in route actions you can have this.referesh()! to reload the model. In this case, you need to add this.sendAction('actionName'); and in route actionName(){this.referesh();}

Related

Issues with model when navigating while still being retrieved

Working with an older ember application (2.18.1). The following problem is repeated too many times to all fix in the time frame I got available right now.
The component is loading it's own data (setting this.get('model')) and all works fine.
However as the database is now a little slower the user sometimes click on one link, where the template render the component and it start loading it's data .
If the user click another link (to a route that does exactly the same) data from both the previous and the "new" component get loaded.
I can't reset the model when data get loaded, since the fetchRecord method that loads the data get called over and over with paging (as the user scroll down).
I'm sure I'm just not thinking of an obvious solution (did not work on Ember for a few years), any advise?
(ps: some of these components does not use paging, in mean time I'm going to clear out the model before setting it to what the api returns)
I'm afraid ember-data gives no support to abort a request, but you can handle that yourself directly on your component calling the endpoint through Ajax or fetch, and then pushing the payload or aborting requests using the lifecycle hooks. For example, you can trigger the abort() on the willDestroyElement hook.
import $ from 'jquery';
import Component from '#ember/component';
export default Component.extend({
init() {
this._super(...argument);
const xhr = $.get( "ajax/test.html", (data) => {
this.get('store').pushPayload(data);
});
this.set('xhr', xhr);
}
willDestroyElement() {
this._super(...argument);
this.get('xhr').abort()
}
});

How to remove records in store when they are not in server anymore

I have application which may lost connection with server for days and when it finally reconnect some record exist in store didn’t exist in server any more.
I need to remove these records without create flickering in the ui.
I try to fix it but can’t get any where.
store.findall didn’t seems to have option to delete record not returned by server.
I can’t find ways to chain store.unloadAll and store.findAll without have the blank state take effect on the screen and cause flickering
I also can’t find out how to get what actually returned by server without go completely manual (make my own ajax calls,which won’t scale obviously)
I am wondering what everyone else is using in this situation
Thanks for any help
You could override the shouldBackgroundReloadAll and shouldBackgroundReloadRecord implementation on your adapter.
As stated at ember adapter documentation:
This method is used by the store to determine if the store should
reload a record array after the store.findAll method resolves with a
cached record array.
Something like:
// app/adapters/application.js
export default DS.RESTAdapter.extend({
shouldReloadRecord: function(store, snapshot) {
return true;
},
shouldReloadAll: function(store, snapshot) {
return true;
},
// If this method returns true the store will re-fetch a record from the adapter.
shouldBackgroundReloadRecord: function(store, snapshot) {
return true;
},
// If this method returns true the store will re-fetch all records from the adapter.
shouldBackgroundReloadAll: function(store, snapshot) {
return true;
}
});
Reference: https://emberjs.com/api/ember-data/2.15/classes/DS.Adapter/methods/shouldBackgroundReloadAll?anchor=shouldBackgroundReloadAll
You could get all records in store via peekRecord() and then reload() each record. If your UI is not depending on isReloading property of model, reloading should not change view until finished. If your API supports coalesceFindRequests and you make sure to execute the reload for all records of a model in same runloop, this should only trigger one request.
Disclaimer: I did not tested this approach but it should work. Let me know, if you face any issues.

Best way to rollback all changes to an Ember Data model

I am using ember-data to edit a user with automatic model resolution
this.route('user', function() {
this.route('edit', { path: ':user_id'})
});
This works fine and the user can modify all aspects of the model DS.attribute, DS.belongsTo and DS.hasMany.
The user can navigate away in a number of ways, in which case all changes should be removed from the model.
Clicking a Cancel button
Clicking the Broswer Back button
Clicking the Save button, the remote request fails, then navigating away from the page.
Just Clicking some other link on the page which takes them somewhere else.
The changes should only be applied if the user explicitly wants them to by clicking the Save button and the server request is successful.
I considered using ember-buffered-proxy but I am not sure how this will cope with DS.belongsTo and DS.hasMany relationships. Regardless, before saving the model I will need to do buffer.applyBufferedChanges(); before saving and if the server fails I am in the save situation as before.
The willTransition hook in the route seems like the obvious place to do this but how can I ensure all changes are removed from the model given rollbackAttributes() only works for DS.attribute controls.
Try utilizing the Ember.Route refresh() method inside the route's willTransition() action hook, like this:
action: {
willTransition() {
const unsavedModel = this.get('unsaved');
if (unsavedModel) {
this.refresh();
}
}
}
The refresh() method can be used for "re-querying the server for the latest information using the same parameters as when the route was first entered."
I've suggested a flag named unsaved, which can default to true, unless it has been set to false at some point during a successful save, prior to transitioning.

Ember.js route hook to be called on every transition

Is there a route hook in Ember.js that is called on every transition, even if the new route is the same as the old route (for example, clicking a top-level navigation link to the same route).
I tried activate, but it's only being called once, and is not being called again when I use the top-level navigation to go to the same route I'm already in.
Example jsFiddle: When I click "Test" the first time, the activate hook is called, but when I click it a second time, it does not.
You can setup a didTransition in the router, exactly how Ember does it for Google Analytics.
App.Router.reopen({
doSomething: function() {
// do something here
return;
}.on('didTransition')
});
See example here: http://emberjs.com/guides/cookbook/helpers_and_components/adding_google_analytics_tracking/
UPDATE: (new link since old is broken)
https://guides.emberjs.com/v1.10.0/cookbook/helpers_and_components/adding_google_analytics_tracking/
Activate is not being called a second time because This hook is executed when the router enters the route... And when you click on that link-to a second time, the router isn't doing anything... As in, no transition is being made (although it is "attempted").
http://emberjs.com/api/classes/Ember.Route.html#method_activate
The method that I have found to work best is observing the currentPath from within a controller. I use this for animations between routes.
In your application controller you can do something like the following:
currentPathChange: function () {
switch(this.get('currentPath')){
case 'test.index':
this.doSomething();
break;
case 'test.new':
this.doSomethingElse();
break;
}
}.observes('currentPath')
You should be able to access almost any part of your app from the application controller, so it's a nice "root hook," I suppose.
Example: http://jsfiddle.net/mattblancarte/jxWjh/2/
Did you already consider the hook willTransition?
http://emberjs.com/guides/routing/preventing-and-retrying-transitions/
App.SomeRoute = Ember.Route.extend({
actions: {
willTransition: function(transition) {
// do your stuff
}
}
});
Alter/Hack EmberJS code and add a jQuery event trigger inside the doTransition() Function. This is Best but kind of defeating the point.
As of today, 1 year later and Ember 2.0 kind of out, there is NO OTHER WAY :(
Ember does not provide a way to track route-change attempts! This includes URLattemts(history), link-to attempts, hash change attempts etc..

Detect model/URL change for Ember Route

My EmberJS application has a ProjectRoute (/project/:project_id) and a corresponding ProjectController. When viewing a particular project, users can edit its properties, and I'd like the project to automatically be saved when the user stops looking at it.
Currently, what I'm doing is something like this:
Application.ProjectRoute = Ember.Route.extend({
...
exit: function() {
this.get('controller').saveProject();
}
...
});
This works when the user simply closest the project view. However, if the user simply switches to viewing a different project (e.g. goes directly from /project/1 to /project/2), the same route is used (it just uses a different model), and exit is not called.
What I need is a way to detect this transition and call the saveProject function before it happens. Any ideas?
I "solved" it by adding the following to my controller:
Application.ProjectController = Ember.ObjectController.extend({
...
saveOnChange: function() {
var previousProject = this.get('target.projectToSave');
if (previousProject && previousProject.get('isDirty')) {
Application.store.commit();
}
this.set('target.projectToSave', this.get('content'));
}.observes('content')
...
});
This seems to work well. Note that I'm storing the projectToSave property in the route (target) as opposed to the controller, because the controller gets wiped every time the model changes. It feels a little weird/hacky to store this in the route, but the only alternative I could think of was to store it in ApplicationController, which seemed overly broad.