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.
Related
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')
});
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 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/
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.
While setting up the application router, I am requesting some data to the backend:
App.Node = DS.Model.extend({
...
});
App.ApplicationRoute = Ember.Route.extend({
processReply: function ( ) { do some processing here; },
setupController: function (controller, model) {
this.cache = App.Node.find();
}
});
Now, when the result of the find is received from the backend, I would like to do some data processing, by calling this.processReply()
How can I listen to the completion of the find request? I have tried plugging in to the .then method (assuming find returns a promise), but this is blocking my application.
setupController: function (controller, model) {
var _this = this;
this.cache = App.Node.find().then(function(data) {
_this.process();
});
}
setupController is synchronous unlike the model hooks. You can delay setting the content of the controller from the promise's then. So the bindings/computed properties from the controller fire after the data has loaded.
setupController: function(controller, model) {
App.Node.find().then(function(data) {
controller.set('content', data);
// optionally
// controller.process()
});
}