Redirect don't work with afterModel - ember.js

I have the following route:
var UserRoute = Ember.Route.extend({
afterModel: function(model) {
// model.ensureAllData();
},
redirect: function (model) {
this.transitionTo('user.followers', model);
}
});
After adding the afterModel hook, the redirection don't work anymore, even the code in the hook commented out.

I guess you should put the transitionTo into the afterModel hook and remove the redirect at all, if I'm not mistaken it was deprecated in favor to the afterModel:
var UserRoute = Ember.Route.extend({
afterModel: function(model) {
//model.ensureAllData();
this.transitionTo('user.followers', model);
}
});
Hope it helps.

Related

Ember when does controller reloads? (or reset)

I've noticed that if i use the same controller for different routes it does not get reset so i can keep data shared between routes which is really helpful for me.
But i wonder... when does the controller reloads in ember? (runs the init and cleans all of his properties)?
And can i manually tell the controller to reload itself?
Thanks for the help guys :)
The controllers are generally singleton instances (excluding itemController instances), they live the life of the page.
If you need to reset some properties you can do it during setupController of the route in need.
App.FooRoute = Ember.Route.extend({
model: function(){
//return something...
},
setupController: function(controller, model){
this._super(controller, model);
controller.setProperties({foo:'asdf', bar: 'ewaf'});
}
});
or you can define some method on the controller that resets it all, and call it during the setupController. Computed properties are all marked dirty and recalculated automatically when the model behind the controller is swapped out.
App.FooRoute = Ember.Route.extend({
model: function(){
//return something...
},
setupController: function(controller, model){
this._super(controller, model);
controller.reset();
}
});
App.FooController = Ember.ObjectController.extend({
foo: 'asdf',
bar: 'wert',
reset: function(){
this.setProperties({foo:'asdf', bar: 'ewaf'});
}// if you want it to happen on init tack on .on('init') right here
});
on init
App.FooController = Ember.ObjectController.extend({
foo: 'asdf',
bar: 'wert',
reset: function(){
this.setProperties({foo:'asdf', bar: 'ewaf'});
}.on('init')
});

Caching `this.get("store").findAll("post")` result set

this route sends server request on every transition to the post.index. Including page reload, navigation and link-to 'post.index'.
I really need to load all the posts once, when that route is transitioned to the first time. What is the best way to cache the result set?
App.PostIndexRoute = Em.Route.extend({
model: function() {
return this.get("store").findAll("post")
}
});
I am using Ember 1.0 and Ember Data 1.0.beta3
In your application route's model/setupController you can prefetch:
ApplicationRoute = Em.Route.extend({
setupController: function(controller, model){
this._super(controller, model);
this.store.find("post");
}
});
And in your post index route you could do:
App.PostIndexRoute = Em.Route.extend({
model: function() {
return this.store.all("post")
}
});

How can I have a code executed every time index is hit?

How can I have a bit of code executed whenever / route is visited?
I have this now:
App.indexController = Ember.Controller.extend({
showFront: function () {
alert("zzz");
}
});
But I am stuck. How can I make it actually work?
You can use beforeModel and setupController hooks to execute code when a route is loaded.
App.Router.map(function(){
this.resource('posts', { path: '/posts' }, function() {});
});
App.PostsRoute = Ember.Route.extend({
// http://emberjs.com/api/classes/Ember.Route.html#method_beforeModel
beforeModel: function() {
console.log("beforeModel fired");
},
// http://emberjs.com/api/classes/Ember.Route.html#method_setupController
setupController: function(controller, model){
this._super(controller, model);
console.log("setupController fired");
},
model: function(){
// resolve the promise after a short delay
return Ember.RSVP.Promise(function(resolve, reject){
setTimeout(function(){
resolve(true);
}, 2000);
});
}
});
beforeModel will fire, as the name suggests, before the model is loaded and setupController will fire after the model has loaded. The example in the JSBin uses a delayed loading model to demonstrate the difference.
This example shows the hooks being used for App.Post route, but you can use this on App.ApplicationRoute if you want to have code execute when loading the default route.
JSBin example
You first need to define a route, and then call a function on it.
Read how here:
http://emberjs.com/guides/routing/defining-your-routes/

while deleting record, transition to another route fails

I'm fairly new to ember.js and I'm doing some experiements. I recently hit a bit of a wall when trying to delete records. Here is my editing route (from which I call delete)
App.PostsEditRoute = Ember.Route.extend({
model: function(params){
return App.Post.find(params.id);
},
exit: function() {
this._super();
tx = this.get('currentModel.transaction');
if(tx)
tx.rollback();
},
setupController: function(controller, model){
controller.set('content', model);
},
events: {
save: function(post){
post.one('didUpdate', this, function(){
this.transitionTo('posts.show', post);
});
post.get('transaction').commit();
},
cancel: function(){
this.transitionTo('posts.show', post);
},
destroyPost: function(context) {
var post = context.get('content');
post.deleteRecord();
post.get('store').commit();
this.transitionTo('posts.index');
}
}
});
So I have a link through which I trigger destroyPost. The record is successfully deleted, and I start to transition to the index route, but an error occurs...
Uncaught Error: Attempted to handle event rollback on while in state rootState.deleted.inFlight. Called with undefined
After this, loading the models for the index page stops and I get an empty page. I can provide any additional code required. Here is the index route.
App.PostsIndexRoute = Em.Route.extend({
model: function(){
return App.Post.find();
},
setupController: function(controller, model){
controller.set('content', model);
}
});
I should note that both of these routes load correctly by themselves. It's only in transition that I get failure.
You need to bind to didDelete like you did with didUpdate in save method.
destroyPost: function(context) {
var post = context.get('content');
post.one('didDelete', this, function () {
this.transitionTo('posts.index');
});
post.deleteRecord();
post.get('transaction').commit();
}
Also, your code seems a bit inconsistent: in the save method you're committing a separate transaction, while in destroyPost you are committing the whole store.

Emberjs scroll to top when changing view

When the main view of my application is switched (new route that reconnects the main outlet of my application controller) I want the page to be scrolled to the top. Otherwise it's a bit strange that I navigate to another page-like view and the viewport is still lost somewhere where I left off.
I hacked a solution and wonder if there's a better way or if anyone has the same thing.
Here's what I do:
App.ApplicationController = Ember.Controller.extend({
connectOutlet: function(){
window.scrollTo(0, 0);
this._super.apply(this, arguments);
}
});
#Baruch's solution is good, but when I implemented it I had render on elements within my application state and would cause a scrollTop when it was not needed.
I found this to be much more effective as it only runs on the path change:
App.ApplicationController = Ember.Controller.extend({
currentPathChanged: function () {
window.scrollTo(0, 0);
}.observes('currentPath')
});
I achieved this with the following code:
Ember.Route.reopen({
render: function(controller, model) {
this._super();
window.scrollTo(0, 0);
}
});
Coffee Script:
Ember.Route.reopen
activate: ->
#_super()
window.scrollTo(0, 0)
Javascript:
Ember.Route.reopen({
activate: function() {
this._super();
window.scrollTo(0, 0);
}
});
You should probably try and extend Ember.Route and add your window.scrollTo in the enter callback. Then instead of using Ember's Route for your leaf routes, you call your route .extend(), so they'll automatically scroll up when you enter a route/state. Something similar to this:
// define your custom route and extend "enter"
var MyRoute = Em.Route.extend({
enter: function(router) {
// for now on, all the routes that extend this,
// will fire the code in this block every time
// the application enters this state
// do whatever you need to do here: scroll and whatnot
}
});
App.Router = Em.Router.extend({
enableLogging: true,
location: 'hash',
index: Em.Route.extend({
route: '/',
connectOutlets: function(router) {
...
},
// on your leaf routes, use your own custom route that
// does your scroll thing or whatever you need to do
home: MyRoute.extend({
route: '/',
connectOutlets: function (router, context) {
...
}
}),
// other routes...
})
});
does it make sense?
It's now render(name, options), and if you are specifically calling render (ie with a modal) you want to pass that to super()
Ember.Route.reopen({
render: function(name, options) {
if (name != null) {
return this._super(name, options);
} else {
return this._super();
}
}
});
Ember 3.12+ (this is technically 3.20 code listed here)
import EmberRouter from '#ember/routing/router';
const Router = EmberRouter.extend({
init() {
// call event everytime route changes
this.on('routeDidChange', () => {
this._super(...arguments);
window.scrollTo(0, 0); // scrolls to top
});
}
});
Router.map(function () {
// your mapping code goes here
});
export default Router;
Prior to 3.12 (this is technically 3.4 but the key code should be the same)
import EmberRouter from '#ember/routing/router';
const Router = EmberRouter.extend({
didTransition() {
this._super(...arguments);
window.scrollTo(0, 0);
}
});
Router.map(function () {
// your mapping code goes here
});
export default Router;
We have handled this problem serveral times and the way we've found that is the easiest and most straight-forward way is to configure this once in the router.js file using a 'route transition' event function. We used didTransition before it got deprecated in Ember 3.12 in lieu of routeDidChange. I've posted both examples below. Some syntax may differ slightly depending on which version of Ember you are on but this core code should be the same.