Ember initializing route model with query - ember.js

I am trying to initialize a Route's model with a DS query, as follows
App.Router.map(function() {
this.resource('post', { path: '/posts/:post_slug' });
});
App.PostsRoute = Ember.Route.extend({
model: function(params) {
var records = App.Post.find({ slug: params.post_slug });
return records.get('firstObject');
}
});
Here, i find a Post by its slug and set the first result as the route model. but since records is populated asynchronously, the model data is not set properly. What is the correct way to do this?

Solved this with Deferred pattern.
App.PostsRoute = Ember.Route.extend({
model: function(params) {
var records = App.Post.find({ slug: params.post_slug });
var promise = Ember.Deferred.create();
records.addObserver('isLoaded', function() {
promise.resolve(records.get('firstObject'));
});
return promise;
}
});

That should do that trick:
App.Router.map(function() {
this.resource('posts');
this.resource('post', { path: '/posts/:post_id' });
});
App.PostsRoute = Ember.Route.extend({
model: function() {
return App.Post.find();
}
});
App.PostRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
}
});

Related

ArrayController Not Updating When Deleting Records

using ember-data 1.0.0-beta.5 and have the following routes and router
App.Router.map(function () {
this.resource('users', function () {
this.route('new');
});
this.resource('user', { path: '/user/:id' }, function () {
this.route('edit');
});
});
App.UsersIndexRoute = Ember.Route.extend({
model: function(){
return this.store.findAll('user');
},
setupController: function (controller, data) {
this._super(controller, data);
}
});
App.UserEditRoute = Ember.Route.extend({
model: function() {
return this.store.find('user', this.modelFor("user").id);
},
setupController: function (controller, data) {
this._super(controller, data);
},
actions: {
delete: function(){
var router = this;
var model = this.currentModel;
model.destroyRecord().then(function(){
router.transitionTo('users');
});
}
}
});
However when i transition back to the users route the ArrayController still has the deleted object in it. Any ideas as to why this is or how to wait until it is removed before transitioning?
kind of a work around but solves the problem.
in the UsersIndexContoller add a array to store the deleted ids
App.UsersIndexController = Ember.ArrayController.extend({
deleted: []
});
Then just append the id of the deleted model to this array and filter in the setupController method.
App.UsersEditRoute = Ember.Route.extend({
delete: function(){
var router = this;
var model = this.currentModel;
var usersController = this.controllerFor('users.index');
model.destroyRecord().then(function(){
usersController.get('deleted').push(model.id);
router.transitionTo('users');
});
}
}
});
App.UsersIndexRoute = Ember.Route.extend({
setupController: function (controller, data) {
var deleted = this.controller.get('deleted');
var filtered = data.filter(function(user){
return !deleted.contains(user.id);
});
data.set('content', filtered);
this._super(controller, data);
}
});
In your case since you want to refetch all of the users and your server lies to you about deleting the record (or it happens later), you might contemplate transitioning then deleting.
delete: function(){
var model = this.currentModel;
this.transitionTo('users').then(function(){
model.destroyRecord();
});
}

Save record of model is not working in ember-data 1.0.0-beta.3?

What I have done -
Model -
App.Book = DS.Model.extend({
book_name: DS.attr('string'),
edition: DS.attr('string')
});
Router -
App.Router.map(function() {
this.resource('books', function() {
this.route('new');
});
});
App.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('book');
},
actions: {
save: function() {
this.modelFor('newBook').save();
}
}
});
Now Can anybody help me.. How to save data ?
I am getting error like
TypeError: this.modelFor(...) is undefined
this.modelFor('newBook').save();
It is hard to tell how the context of your action looks like.
But one option is to pass the object you want to save as a parameter like this {{action save myBook}}.
Then you action could look like this:
App.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('book');
},
actions: {
save: function(book) {
book.save();
}
}
});
I think this should work.
App.BooksNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('book');
},
actions: {
save: function() {
this.get('model').save();
}
}
});

Why don't nested resources in Ember.js preserve the params hash?

Given the following Ember.js application (using Ember 1.0.0.rc.6.1 and Ember Data 0.13):
App = Ember.Application.create({ LOG_TRANSITIONS: true });
App.Store = DS.Store.extend();
App.Router.map(function() {
this.resource('promotions', function() {
this.resource('promotion', { path: '/:promotion_id' }, function() {
this.resource('entrants', function() {
this.resource('entrant', { path: '/:entrant_id' });
});
});
});
});
App.PromotionRoute = Ember.Route.extend({
model: function() {
return { id: 1, name: 'My Promotion' };
}
});
App.EntrantsIndexRoute = Ember.Route.extend({
model: function(params) {
console.warn('EntrantsIndexRoute', '\nparams:', params, '\nparams.promotion_id:', params.promotion_id, '\narguments:', arguments);
console.log('params should be:', { promotion_id: 1 });
console.log('The queried URL should be:', '/entrants?promotion_id=1');
return App.Entrant.find({promotion_id: params.promotion_id});
}
});
App.Entrant = DS.Model.extend({
name: DS.attr('string')
});
If you enter the url #/promotions/1/entrants, which should be a nested resource, the params is an empty object. How can I access promotion_id there? JSFiddle here, take a look at the console after clicking on "Click me": http://jsfiddle.net/Kerrick/4GufZ/
While you can't access the dynamic segments of the parent route, you still can retrieve the model for the parent route and get its ID, like this:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
var promotion_id = this.modelFor('promotion').id;
return App.Entrant.find({ promotion_id: promotion_id });
}
});
Or, if there is a has-many relation between promotion and entrants, you even might do:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
return this.modelFor('promotion').get('entrants');
}
});
Try this code:
App.EntrantsIndexRoute = Ember.Route.extend({
model: function() {
var promotion_id = this.modelFor('promotion').query.promotion_id;
return App.Entrant.find({ promotion_id: promotion_id });
}
});

How to fetch a ember model with a more complex url

I'm using EmberData and wonder how I can I fetch a model from path like this:
products/:id/comments
Considering that you are using the default RESTAdapter, this is one possible way — although I'm not sure if it's the best one:
App = Ember.Application.create();
App.ProductCommentsRoute = Ember.Route.extend({
model: function() {
var productId = this.controllerFor('product').get('model').get('id');
return App.Comment.find({ product_id: productId });
}
});
App.Router.map(function() {
this.resource('products', function() {
this.resource('product', { path: ':product_id' }, function() {
this.route('comments');
})
});
});

How do I use dynamic segments in EmberJS' 2.2 router?

I can't figure out how to create routes with dynamic segments in the new router API for EmberJS. I've spent a week on it and tried many things but it doesn't work. I am really frustrated at myself because I've gone through the docs, API and source code many times and cannot figure out how to make this work. I am dying for assistance.
I am trying to achieve the following routes:
/profile/:userId -> index
/profile/:userId/activity -> activity page
/profile/:userId/...
My router is set up like this
App.Router.map(function() {
return this.resource("profile", function() {
this.route("index", { path: '/:userId' });
this.route("activity", { path: '/:userId/activity' });
});
});
Then, whenever I try to link with the linkTo helper, I receive the following error: Uncaught More objects were passed than dynamic segments
<li>{{#linkTo "profile.index" user}}overview{{/linkTo}}</li>
If I don't include the user object, then I receive another error Uncaught Error: assertion failed: Cannot call get with 'id' on an undefined object. (obviously because there's no object to take the ID of)
If it's any helper, here are my route declarations
App.ProfileIndexRoute = Ember.Route.extend({
model: function(params) {
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
App.ProfileActivityRoute = Ember.Route.extend({
model: function(params) {
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
JSBin example
You can structure your routes with a little bit more nesting to get the URLs you desire (and you don't need to have a return statement in your router):
App.Router.map(function() {
this.resource("profile", function() {
this.resource("userprofile", { path: '/:userId' }, function() {
this.route("index", { path: '/' });
this.route("activity", { path: '/activity' });
});
});
});
and then set up your routes like this:
App.IndexRoute = Ember.Route.extend({
model: function(params) {
return [Ember.Object.create({
id: 1
})];
}
});
App.UserprofileIndexRoute = Ember.Route.extend({
model: function(params) {
console.log("userindex route", params);
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
App.UserprofileActivityRoute = Ember.Route.extend({
model: function(params) {
return Ember.Object.create({
id: 1
});
},
setupController: function(controller, model) {
return controller.set("content", model);
}
});
You can link to the /profile/1 page:
{{#linkTo userprofile.index user}}
or link to the /profile/1/activity page:
{{#linkTo userprofile.activity user}}