modelFor parent route stopped working as before - ember.js

Given the following routes:
App.Router.map ->
#resource 'locations', path: '/:location_id', ->
#route 'events', path: '/events/:date'
App.LocationsEventsRoute = Ember.Route.extend
model: (params) ->
location_id = #modelFor('locations').get('id')
console.log location_id
Accessing "/#/gothenburg-se/events/2013-09-03", location_id returns null. This worked before v1.0. What changed and how do I fix this?

This is likely due to changes in Ember Data for 1.0.beta.1. You might want to check out the transition document.
https://github.com/emberjs/data/blob/master/TRANSITION.md
I think something like this would work for your route:
App.LocationsEventsRoute = Ember.Route.extend({
model : function(params){
// find returns a promise
var locProm = this.store.find('location',params.location_id);
// once the promise has resolved you can log the id
locProm.then(function(loc){
console.log( loc.get('id') );
});
// return the promise immediately and let Ember resolve it
return locProm;
}
});

Related

Ember update parent route's model after save record

I'm working on an Ember application with the intent of learning. I've setted on a UI where a parent route and template when first opened features a table of, for example, today’s items in the left hand column, and an area to the right that varies: details about an item, form for new/edit item, search, etc.
The trouble I have run into is that when I save a new item, the left hand table from the parent route is not updated with the new item. Having trouble finding a way of getting that route to refresh. The closet I came was by using pushObject on the model.
things template:
{{partial "things/table"}}
{{outlet}}
router.coffee
#resource "items", ->
#route "item", {path: "/:item_id"}
#route "new", {path: "/new"}
items route:
ItemsRoute = Ember.Route.extend(
model: -> #store.find 'item'
)
items new route:
ItemsNewRoute = Ember.Route.extend
renderTemplate: ->
this.render('items/form')
model: ->
#store.createRecord('item')
setupController: (controller, model)->
controller.set('model', model)
items new controller:
ItemsNewController = Ember.ObjectController.extend(
needs: 'items'
actions:
submit: -> #model.save().then(console.log('saved'(, console.log('failed'))
cancel: -> #transitionTo('items')
transitionAfterSave: (->
if #get('content.id')
#transitionToRoute('items.item', #get('content'))
).observes('content.id')
submit: -> #model.save().then(this.didSave.bind(this), console.log('failed'));
didSave: function() {
console.log('saved');
var route = this.container.lookup("route:items.index"); // use the name of route you want to refresh
route.refresh();
}

Setting the model in a nested route in Ember.js

I have a nested edit route:
#resource 'dashboard.communities.community', path: ':community_id', ->
#route 'edit'
In my route, I try to retrieve the model with modelFor:
CivicSourcing.DashboardCommunitiesCommunityEditRoute = Ember.Route.extend
model: (params, queryParams, transition) ->
#modelFor('community')
But this returns undefined. The parent route is successfully retrieving the community, though. Any idea what might be going on?
You're resource name is dashboard.communities.community not community
#modelFor('dashboard.communities.community')
Here's a similar example for colors.cool
http://emberjs.jsbin.com/OxIDiVU/442/edit

Using transitionToRoute with a model with a custom slug

I've got an ember-data model that has an id as well as a server-generated custom slug attribute (which is prefixed with the id if that matters).
I'd like to use the slug instead of the id in all public routres. For that purpose, I have changed the router:
App.Router.map ->
#resource 'strategies', path: '/strategies', ->
#resource 'strategy', path: ':strategy_slug'
and overwrote the serialize method of the respective route:
App.StrategyRoute = Ember.Route.extend()
serialize: (model) ->
{
strategy_slug: model.get('slug')
}
Unfortunately, this does not seem to work when using transitionToRoute from a controller to transition to, e.g., /strategies/123-test:
App.ExampleController = Ember.ObjectController.extend()
[...]
actions:
showDetails: ->
#transitionToRoute("/strategies/#{#get('slug')}")
false
(where #get('slug') returns '123-test')
All output I get in the console after invoking the showDetails action is:
Transitioned into 'strategies.index'
Ember does seem to recognize the slug-based route.
Ember: 1.5.0-beta.2+pre.3ce8f9ac
Ember Data: 1.0.0-beta.6
Is there anything I may have missed?
Edit:
The following variant works and is feasible in this case, but I have another use-case where I have only access to the URL.
App.ExampleController = Ember.ObjectController.extend()
[...]
actions:
showDetails: ->
#transitionToRoute('strategy', #get('content'))
false
I eventually figured out how to solve this. The key is to add a model method to the router, which knows how to turn a slug into a model:
App.StrategyRoute = Ember.Route.extend()
model: (params, transition) ->
App.store.getById('strategy', parseInt(params.strategy_slug))
serialize: (model) ->
{
strategy_slug: model.get('slug')
}

Proper way to use parent route parameters with ember-data?

In my app, I am trying to keep the routing structure as close to the API structure as possible, which ember facilitates in the basic case but I am still confused about the following case:
(In reference to the example of http://emberjs.com/guides/outlets/#toc_nesting)
What is the best way to go about retrieving the /posts/:post_id/comments data (assuming it isn't given to me by /posts/:post_id)?
Should I be passing the post ID to App.Comment.find(...) somehow, in the comments.deserialize(...) method? Is there a better way to get the post ID than router.getPath('postController.content._id')? I am using a modified DS.RESTAdapter.
Parent router parameters are no more accessible as parameters in children routes, but should have been used to retrieve and populate intermediate data structure.
Given your models are defined as follow:
App.Post = DS.Model.extend({
text: DS.attr('string'),
// ...
comments: DS.hasMany('App.Comment')
});
App.Comment = DS.Model.extend({
// You may also have: "post: DS.belongsTo('App.Post')", but we do not care for this exemple
text: DS.attr('string'),
// ...
});
This should be something working:
posts: Ember.Route.extend({
route: 'posts',
member: Ember.Route.extend({
route: '/:post_id', // [A]
connectOutlets: function (router, post) {
var applicationController = router.get('applicationController');
applicationController.connectOutlet('post', post); // [B]
},
show: Ember.Route.extend({
route: '/'
}),
comments: Ember.Route.extend({
route: 'comments',
connectOutlets: function (router) {
var postController = router.get('postController'),
comments = postController.get('comments'); // [C]
postController.connectOutlet('comments', comments);
},
}),
})
})
[A]: The post model instance will be retrieved automagically by the router, according to convention: post_id refers to Post model instance with the given id (see this comment).
[B]: Here, PostController will be populated by the router with the passed context: post, which is the Post instance retrieved upper (see [A]).
[C]: PostController is an ObjectController (i.e Proxy) on the post model instance, so it directly holds comments.

Ember Router - Load content from different controller on same level

Having two routes (comments, trackbacks) nested within post I try to access content of commentsController from trackbacksController after entering the App directly through /posts/1/trackbacks. Unfortunately it seems like the controller is not fully initialized and the content doesn't get loaded.
This is how the Router looks like:
Router = Ember.Router.create
root: Ember.Route.extend
index: Ember.Route.extend
route: '/'
post: Ember.Route.extend
route: '/posts/:post_id'
index: Ember.Route.extend
route: '/'
redirectsTo: 'comments'
comments: Ember.Route.extend
route: '/comments'
connectOutlets: (router) ->
controller = router.get('postController')
controller.connectOutlet 'comments', controller.get('comments')
trackbacks: Ember.Route.extend
route: '/trackbacks'
connectOutlets: (router) ->
controller = router.get('postController')
controller.connectOutlet 'trackbacks', controller.get('trackbacks')
And here is the TrackbacksController:
App.TrackbacksController = App.ArrayController.extend
init: ->
console.log App.router.get('attributesController.content') # : []
#_super()
Is there a best practice to initialize router.commentsController manually to get it's content from trackbacksController? Is there anything wrong concerning my approach?
You can access all controllers from a controller, using its controllers property.
For example, from trackbacksController, you can use this.get('controllers.commentsController')
EDIT: I realize I did'nt get your problem. I think there is some dependencies between the two controllers, and from my point of view, you can't rely on the application initialization order. So in the init method, you will not be able to access other controllers.
But I think you can put an observer in the trackbacksController, which observes controllers.commentsController.content or controller.commentsController.#each, so when the commentsController is populated, you will be notified.