Ember (data) linkTo without passing model, just fetch new model - ember.js

When using the linkTo helper in a handlebars template, Ember sets up the correct URL for the link with the help of the serializer I have added to the route:
serialize: function(slug, params) {
var name, object;
object = {};
name = params[0];
object[name] = slug;
return object;
}
And when I click the link, Ember transitions to the correct page with the correct slug and everything, but it doesn't have the correct data, and it says that. I believe it's because what I pass to my linkTo statement as second parameter is just the slug and not the whole model.
Is it possible to get Ember to simply fetch the data as it would if I just typed the URL into the address bar instead of relying on the model (that is not) passed to the linkTo statement?
UPDATE
I have tried this inside the activate method on my route, but now it seems the problem is that the rendering has to wait until this is done.
activate: function() {
this.context.isLoaded = false;
this.model(this.context.query.slug);
}
Any ideas? Maybe even with a prettier solution?

The solution I came up with at last, with help from some guys on IRC, was to use the setupController hook, like you mention, Darshan, and the serializer like this:
CustomRoute = Ember.Route.extend({
setupController: function(controller, model) {
var modelName = this.routeName.substr(0, 1).toUpperCase() + this.routeName.substr(1),
slug = model;
if (model.hasOwnProperty('slug'))
slug = model.slug;
controller.set('model', App[modelName].find({'slug': slug}));
},
serialize: function(slug, params) {
var name, object;
object = {};
name = params[0];
object[name] = slug;
return object;
}
});
This way, you can supply just the slug of the route as the second parameter to the linkTo helper instead of a model, and the serializer will set the URL up properly, and then the setupController will check if the model has a property slug, which properly means it's a proper model, and if it does not, it just guesses that the model is simply the slug, and then it will use the DS.Model.find method to return a promise to the controllers model store.
Because setupController is called everytime a route is entered, where as the model hook is only called sometimes, the DS.Model.find method will be used everytime to fetch the data via the promise, and voila - fetch data each time you enter a route.
This assumes that you use Ember.Data and that your model object is called App.*route name* starting with a capital letter, but it can easily be modified to fit whatever need one might have.
For all of the routes in my app I now subclass (extend) from this route thus getting my desired behaviour for all of my routes.

You can try using the slug name in the Route and then loading data for the Route using findQuery instead of find.
App.Router.map(function() {
this.resource('product', { path: '/product/:slug' });
});
App.ProductRoute = Ember.Route.extend({
model: function(params) {
return App.Product.query({name:params.slug});
}
});

Related

Params empty in model hook, but paramsFor is not empty

The example code below is how the model hook is supposed to work by default. Strangely, if I don't include the model hook at all, the model is populated correctly. If I include the model hook as below, it doesn't work because "params" is an empty object. However, this.paramsFor('somemodel') returns {somemodel_id: "1"} So, what am I missing here?
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
return this.store.find('somemodel', params.somemodel_id);
}
});
Nested routes inherit the parent route's model if you do not specify a model hook. If all you are doing is looking up the model to edit you don't need a model hook, if you are querying the store for something else and need access to somemodel you can access it via this._super(...arguments).
export default Ember.Route.extend({
model: function(params) {
return this.store.find('somemodel', this._super(...arguments).get('id'));
}
});
It seems that params don't propagate to nested routes. My router looks like this:
this.route('somemodel', { path: '/somemodels/:somemodel_id' }, function() {
this.route('edit');
});
The "index" route is implied and is the route that receives the params. The edit route is nested and does not receive the params.

accessing Ember data store from a controller / multiple data on model hook

I have a model hook that returns a list of reviews from the data store. On that same page, I have a review form. When the form is submitted, I call an action on the controller and I need to call createRecord() on the store. Normally I would pass a created record from a model hook but my model hook is already taken. What is the best approach here?
It would be a lot better to create this record in the model hook and use it across the form, e.g. for making validations if needed. You can use Ember.RSVP.hash for having multiple models fetched in model hook:
model: function() {
data = {
reviews: store.find("review"),
newReview: store.createRecord("review")
};
return Ember.RSVP.hash(data);
}
Than, in your setupController:
setupController: function(controller, model) {
// all your data is in model hash
controller.set("model", model.reviews);
controller.set("newReview", model.newReview);
}
Thanks to that, you would have your newReview object from the beginning in the controller. You can set bindings directly to it in your form and make validations on the fly. It's better way, as it does not need to copy data from the form to the object by hand, but rather take advantage from ember bindings system, like that.
All you would have to do in your action would be:
actions: {
save: function() {
this.get("newReview").save();
}
}
When the form is submitted, I call an action on the controller and I need to call createRecord() on the store. Normally I would pass a created record from a model hook but my model hook is already taken.
I don't know what you mean by "pass a created record from the model hook". Pass from where to where? If you want to create a record, just create it in the action. Then you can update the controller's model with the new record:
// controller
actions: {
addReview() {
function create() { return store.createRecord('review', ...); }
function push(review) { model.pushObject(review); }
var store = this.get('store');
var model = this.get('model');
create() . save() . then(push);
}
}
Or something similar.

Use of serialize hook in ember routes

What is the use of serialize hook in ember route class?
App.PostRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('post', params.post_id);
},
serialize: function(post) {
return { post_id: post.get('id') };
}
});
Ember Documentation says:
If your dynamic segment ends in _id, the default model hook will convert the first part into a model class on the application's namespace (post becomes App.Post). It will then call find on that class with the value of the dynamic segment.
The default serialize hook will pull the dynamic segment with the id property of the model object.
But i am not able to understand the use of serialize hook in route class
The serialize method determines what to use as parameter for the provided entity.
Example.
Say you have the following user model, with the following properties.
id
username
email
Now if you have a list of users, and you want to link to a show user details page, you might use a loop like this.
{{#each users}}
{{#link-to user.show this }} {{username}} {{/link-to}}
{{/each}}
So when Ember sees this link-to helper i will convert it to a link, which might look like this
elvar
Now the default behavior here is to use the id as a parameter, which is what your own example shows, i picks the id from the model. We can change this with the serializer method.
Lets say that instead of using the id, we want to use the username as a parameter.
App.UserShowRoute= Ember.Route.extend({
model: function(params) {
return this.store.find('user', params.user);
},
serialize: function(user) {
return { user: user.get('username') };
}
});
Now the link-to helper will yield the following instead.
elvar

What's the best approach to "force" the model hook to fire?

I'm using ember.js 1.2 and one of my routes has a very dynamic model. When I jump into the route for the first time or when I paste in the url the model hook of the route fires, then setup controller fires and everything works as expected.
The problem occurs when I come into the route later (but not from the url directly) -this only hits the setupController hook (and the model method never fires). But technically what's changed is the url (and the parent model). And with this model, it's primarily defined from the parent (using that parent model to fetch a new set of dynamic configuration at runtime).
So how can I force the setupController to re-execute the model hook each time this specific route is loaded? (as if the model method was firing each time).
Or ... Should I fetch this dynamic model in setupController and keep the model hook logic-less by having it return an empty object?
Update
App.ChildIndexRoute = Ember.Route.extend(App.ModelMixin, {
setupController: function(controller, model) {
this._super(controller, model);
var parent = this.modelFor('parent');
return this.getForParent(parent).then(function(things) {
controller.set('model', things);
});
}
});
You can use the setupController hook instead of the model hook, it's a perfectly acceptable way to handle it.
And technically the transition is what calls the model hook and supplies it to the setupController.
Where in the chain is it not firing the model hook? Here's a simple app with a few nested resources.
http://emberjs.jsbin.com/AtebAsOS/6/edit
The key bit of code in this example is in the DogsRoute:
App.DogsRoute = Em.Route.extend({
setupController: function(controller, model){
model = Em.get(this.modelFor('cow'), 'dogs');
this._super(controller, model);
}
});
From the docs:
[The setupController] method is called with the controller for the current route and the model supplied by the model hook.
So when you override the model with the fetched dogs model and pass it to _super, the controller will use the freshly fetched model.

Emberjs: controller and route not getting along

The example will represent it best, I suppose. So, I have a defined route with a model property, which displays the appropriate image, based on id in url. This worked:
App.DetailsRoute = Ember.Route.extend({
model: function(params) {
return App.Images.find(params.image_id);
}
});
However, I wanted to add an action and... when I set up the controller, the page did not have access to the model part. Controller:
App.DetailsController = Ember.Controller.extend({
saveToServer: function(){
//alert(JSON.stringify());
alert('hi');
}
});
So at this time it's like this: either the model is set and stuff gets displayed and controller doesn't work OR controller works and model not.
Why is this happening?