When you transition from index.html#/admin/authors/1/edit to index.html#/admin/authors/2/edit, deactivate on the route is not called.
When you transition from index.html#/admin/authors/1/edit to index.html#/admin/authors/new, deactivate on the route is called.
I would expect that in both cases deactivate is called ?
Is there another method at route level to detect that you switch from ../1/edit to ../2/edit ?
I need this in a master detail view (master is list with all authors, detail is form with textfields for each of the author properties). If the users selects another author in the list and the previous author was modified without saving, I need to rollback the transaction or ask the user 'do you want to save changes ?".
Deactivate is not called in this case since the edit route is still active. To detect switching from ../1/edit to ../2/edit use the route's willTransition event. For example:
App.FormRoute = Ember.Route.extend({
actions: {
willTransition: function(transition) {
if(!this.controller.get('canNavigate')) {
alert('non-empty form!');
transition.abort();
}
}
}
});
See this gist for more examples: https://gist.github.com/machty/5647589
Related
How can I change the data of the model on a route as a reaction on a user interaction like pushing the button?
I want to have a productsearch-route where the model holds the items. This set on items can change when the user clicks sets criteria and clicks search. I have a component which sends an action every time the user fills a form and presses the button "search". The route handles the action in
//rounte.js
action: {
searchClicked: {
var newdata = this.get('store').query('item', {...});
this.set('model', newdata); //<<<< this is not working!!
}
}
If im doing so, exceptions will approaching. Also im afraid that this can't work even if if there are no exceptions because the template wont update itself I guess.
However:
How can I set(/completely exchange) the model from actions in a route?
I could think of few ways:
1) use query params and force route to refresh the model when criteria changes. More can be found here : https://guides.emberjs.com/v2.3.0/routing/query-params/, specially Opting into a full transition. But this might not suite your need if you can have multiple criterion.
2) Set model to the controller not the route.
actions: {
searchClicked() {
let promise = this.get('store').query('item', {...});
promise.then(newData => {
this.controller.set('model', newdata);
});
}
}
but with controllers going away in future iteration of ember, I don't know if this is best solution either.
I'm currently working on an Ember app and it is coming along fine but since I am new to MVC applications in general there are a lot of concepts that don't come naturally to me.
I am currently trying to return two models for my index route. I referred to another SO question (EmberJS: How to load multiple models on the same route?) for the correct method and it has worked great.
My problem is now that I need to only set one of the two models only if the user is authenticated. I am using ember-simple-auth, and currently this is what I've got:
// app/routes/index.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
if (this.get('session.isAuthenticated')) {
var _this = this;
this.get('store').find('user', this.get('session.uid')).then(function(user) {
_this.set('model.entries', user.get('entries'));
});
}
return Ember.RSVP.hash({
newEntry: this.get('store').createRecord('entry', {
body: 'Write here ...'
})
});
}
});
For some reason, this does not work. After my route is loaded, the model only has the 'newEntry' property and not an 'entries' property, although the promise does get fulfilled (I put console.logs inside to prove it).
What could be happening? And is this the best way to accomplish this?
There is a set of data that you always want to load, for every user. Do that in the model hook, that is actually the data for the route.
There is another piece of info that you want to add only if a condition is met (authentication). Do that in the afterModel hook.
...is provided the route's resolved model...
http://emberjs.com/api/classes/Ember.Route.html#method_afterModel
So, now you can append or remove data from the model. Or take any relevant action depending on the data that you received.
Is it possible to update a dynamic parameter in the URL for the current route without recreating the route's view?
Specifically, say I have a route that handles post/:post_id. The view for this route shows the post with the given id but (in an infinite-scroll style) also allows the user to smoothly scroll down to subsequent posts. I'd like to update the url to reflect the post they are currently viewing. If I call reaplceWith('post', newlyFocusedPost) the renderTemplate hook fires, my original view is destroyed, a new view rendered, and the smoothness is lost.
I'd love the equivalent of Backbone.js's:
router.navigate('posts/123', {navigate:false, replace:true});
Another solution would be if rendering the same template into the same outlet reused the existing view and just updated its bindings.
(My current solution is to use a subroute, postAtId, that handles the dynamic id with no view plus a call to controllerFor('post').set('content', newPost))
Re-rendering when only the context has changed is arguably a bug. There is a pull request that fixes this.
But it's also possible to work around this behavior in your own route by overriding renderTemplate so that it only renders immediately after entering the route for the first time. For example:
App.MyRoute = Ember.Route.extend({
activate: function() {
this.needsToRender = true;
},
renderTemplate: function() {
if (this.needsToRender){
this.needsToRender = false;
render();
}
}
});
I have an Ember application composed from 3 routes:
router.route('territory', { path: 'localhost/app/territory/:tid' });
router.route('aggregator', { path: localhost/app/territory/:tid:/aggregator/:aid' });
router.route(territory, { path: 'localhost/app/territory/:tid/aggregator/:aid/item/:iid' });
the possibles transition are from territory to aggregator, from aggregator to item, and from item to a sub item.
The sub item use the same route (the 3rd), just changing the iID value in the model of route.
I had created an action that allows the user to move into a particular route with some logic and at the end run the command:
model={
tid: "ttt"
aid: "aaa"
iid: "iii"
}
destination = 'item'; //the name of item route
controller.transitionToRoute(destination, model);
If I'm in the item route and I want to move to an other item, the URL will update, but not the content of the page. Obviously if I refresh the page with the generate URL the content will update.
Where is the problem? in the transition method that is Deprecated, or i have to use something different?
IMPORTANT: I'm using EmberJS - V1.0.0-RC.1
Is not a bug is just a normal situation in emberjs because every route have model and setupController.
The model function is used to retrive asynchronously from WS or Data module the necessary information (is a RSVP.Promise). When is complete the information will be passed to setupController function, where will be possible set properties of the controller connected with the view of current route.
Every time that i change the value of path but not the route, only setupController will be called.
To conclude, in my case, the problem was just an organisation problem of code.
I have a Router set up which looks like this:
Social.Router.map(function() {
this.resource('accounts', function(){
this.resource('account', { path: ':account_id'});
});
});
When the account route is entered I'm using the activate method to do some DOM manipulation.
Social.AccountRoute = Ember.Route.extend({
activate: function(){
console.log('entered the account route')
}
});
This works great, the first time the account route is entered. Problem is that I have the ability to change from account to account without leaving the account route. Meaning that I can go from:
account/1
to
account/2
but the activate method only fires one time, the first time I enter the account route. Is there a method that will fire every time the account_id slug changes?
Not a very intuitive solution, but there are 3 methods that are executed every time the model changes:
serialize
setupController
renderTemplate
activate and deactivate are only triggered when entering a new route. However, the methods model, setupController, and serialize will be called with each change of /account/:account_id. (Edit: as pointed out by #mavilein in the comments, model will only be called when triggered by a URL change, and I left off renderTemplate).
Regardless, your routes and controllers shouldn't be concerned with DOM manipulation. Leave that to your views and templates by binding to significant values or observing changes in your controller(s).