Ember - How to get route model inside route action - ember.js

Is it possible to access route model inside route action?
I am passing multiple objects inside a route model to template,
model: function() {
return {
employeeList : this.store.findAll("employee"),
employee : Ember.Object.create()
}
}
From the route action I am want to modify the route model.employee. I tried the following, but I am not getting the object.
actions:{
editAction : function(id) {
var emp = this.get("model");
console.log(emp.employee);
}
}
Can anyone give a solution to get and modify model object(employee)?

First problem is that you should return a promise from the model hook. That way, the transition will wait for the promise to Resolve. return { /*...*/}; returns an object and not a promise, even if the object itself contains promises.
The solution is to use Ember.RSVP.hash like:
model() {
return Ember.RSVP.hash({
employeeList: this.store.findAll('employee'),
employee: Ember.Object.create()
});
}
This will return a promise that resolves when all inner promises resolve.
The second problem is that you can't use this.get('model') in a route. If you think about it the model property is the hook itself and not the resolved model. Solutions:
That action is sent from the controller/template. Can't you pass the model as a parameter? That way you could access the model through the function arguments.
If you absolutely need to, this.modelFor(this.routeName); returns the model for the current route.
You can access the model in route through the controller like this.controller.get('model').
You could also implement the setupController hook and access there the model. You can then do things like this.set('employeeModel', model); for later access.

this.get('context')
gives you access to the model in the route action.

Related

Making a child route's model query dependent on parent route - promises?

I'm new to Ember and getting very stuck! I have a child route that needs to wait for the parent route to return it's record set. The child route then needs to do a findByIds for all the keys returned in the parent route (parent returns many keys). My child route looks like this:
export default Ember.Route.extend({
model: function(params, transition) {
var allPermissions = Ember.ArrayProxy.create({ content: this.modelFor('permissions') });
return this.store.findByIds('outlet', allPermissions.map(function(item, index, enumerable){
console.log('in map');
return item.get('howya_system_key');
}));
}
});
What I'm trying to do here is get all the parent route records, then return the result of of findByIds on each of the parent id's returned.
When I transition into the route it does not error and there is no output from the console.log. I think my problem is that the new ArrayProxy has not been created by the point that findByIds is executed so allPermissions.map has nothing to iterate over.
I'm guessing that I need to implement this via a Promise though I can't see how I'd do it. Can anybody point me in the right direction?
Much appreciated.
UPDATE:
I think I've worked out how to do this but I'm not sure I'm doing it the 'Ember' way. I've added a promise and my route now looks like this:
export default Ember.Route.extend({
model: function(params, transition) {
var _this = this;
return new Ember.RSVP.Promise(function(resolve) {
resolve( _this.store.findByIds('outlet', _this.store.peekAll('permission').map(function(item, index, enumerable){
console.log(item.get('howya_system_key'));
return item.get('howya_system_key');
})))
});
}
});
Question is, is there a better way and is 'peekAll' the best thing to be using or am I going to end up looking at all store records for a model, rather than just store records for a model related to a parent route query?
UPDATE
OK, solved this. Can't use relationships as suggested below as the parent keys can point at different tables depending on type.
The solution was to use the promise as defined above, but use:
_this.modelFor('ROUTE_NAME').map
Instead of:
_this.store.peekAll('MODEL_NAME').map
I'll also need to filter the ID's to search for depending on Type and present different types in separate routes - but that's for another day.
For the final outcome of this where I was shown how to use the promise correctly, please see my other question

ember-data model is not being deleted when transitioning a route

I need to delete a model when I leaving a route. I am using the following in the route:
actions : {
willTransition: function(transition){
//Cleanup search model
var model = this.modelFor('route1.index');
model.deleteRecord();
//At this point the model.get('isDeleted') = true
}
}
From ember inspector when I have transitioned to my new route route1.route2, I can still see the model and its isDeleted property is now false.
Why is this not working?
First of all, you willTransition will be also called before you're entering the route, so you have to make sure that the transition's target is different from the current route:
if (transition.intent.name !== this.routeName)
Then, you can probably use something like:
var model = this.modelFor(this.routeName);
instead of manually type the route name.
How did you check that the model is not deleted? Maybe you created a new one?
You need to call the save() method after calling deleteRecord()
actions : {
willTransition: function(transition){
//Cleanup search model
var model = this.modelFor('route1.index');
model.deleteRecord();
model.save();
}
}
Or just use model.destroyRecord(); as it does both

Ember.js accessing model values in afterModel

There is a Question here Ember.js accessing model values from afterModel
but it doesn't exlpain how to access the value in the afterModel hook. Can someone advise?
my model:
model: function () {
return Ember.RSVP.hash({
accounts: this.store.find('account').then(function (account) {
})
});
},
Did you read the documentation? The model is the first parameter passed to afterModel.
https://api.emberjs.com/ember/3.13/classes/Route/methods/transitionTo?anchor=afterModel
On a slightly unrelated note, I wonder why you are returning Ember.RSVP.hash from the model hook. That makes the model (after being resolved) a hash containing a property accounts, which is presumably what you are interested in. That means every time you access the model you have to say model.accounts. Why not just return this.find(... itself, which would make the model itself the array of account instances which you could refer to directly as model?

Getting model data from controller

In Ember if I have a model that is a list of users, if in the UsersController I do:
users = this.get('model');
users.map(function(user) {
user.name
});
should it not resolve the promise and return the user records? I'm confused on why this is not working for me, or how to get the model data the correct way. Thank you in advance.
The model promise is resolved by the router. Ember, by default, sets the controller's content property as the route's model unless you override the route's setupController() method. Your issue lies in the formatting of the map function.
It seems like you're using an array controller, because the model is an array, so do the following:
App.UsersController = Em.ArrayController.extend({
users: function() {
return this.map(function(user) {
return user.get('name');
});
}.property('#each.user'),
});
You can make this code even more streamlined by using Em.Array's mapBy() method, as follows:
App.UsersController = Em.ArrayController.extend({
users: function() {
return this.mapBy('name');
}.property('#each.user'),
});
If you're using the list of users in your template you can do this easily with a {{#each users}} helper. However, if you're using this list for other properties in the controller, be sure to to use the right observer to watch for items being added to the array:
someOtherProperty: function() {
var users = this.get('users');
// Do stuff with users array here...
}.observes('users.[]')
See setting up a route's model and setting up a controller if you're unfamiliar with how the models stuff works.

associating a model with a route in emberjs

As I understad, a template in emberjs gets it's data from controller. So, it's a controller's job to get hold of model data and present it to the template.
The docs here associate a model with a route like this:
App.FavoritesRoute = Ember.Route.extend({
model: function() {
// the model is an Array of all of the posts
return App.Post.find();
}
});
In this case and ArrayController is automatically generated.
However, there's also the setupController function. So, can we also do this :
App.FavoritesRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('model', App.Post.find());
}
});
as the first example given here do?
Do the two ways do the same thing?
Do the two ways do the same thing?
Almost. In both cases the controller's content property will be set to the result of App.Post.find(). And both will work.
That said, using the model hook is the preferred way to do this. If your model hook returns a promise, the router will wait for it to resolve before moving on. That is not the case with the setupController hook. generally you will want to avoid anything async from the setupController hook.