I've scouring for a bit, but can't find an answer to this. I've got an Ember route on a Rails app, and I would like one of the model records to be displayed by default when visiting the URL (right now, a user needs to click on a specific link to retrieve the data).
For example, when visiting /albums, I would like /albums/38 to be active and visible without forcing a redirect. Is that possible?
Thanks
App.Router.map ->
#resource 'albums', path: '/', ->
#resource 'album', path: '/:id'
App.AlbumsRoute = Ember.Route.extend
model: -> #store.find 'album'
Add an 'index' route for the 'albums' resource and redirect to the 'album' route with the first model. The index route will only be hit when you hit just the albums resource, and not when you hit deeper (aka not when you hit /albums/1).
App.AlbumsRoute = Ember.Route.extend
model: -> #store.find 'album'
App.AlbumsIndexRoute = Ember.Route.extend
model: ->
album = this.modelFor('albums').get 'firstObject' # This can be whatever...
this.transitionTo('album', album) if Ember.isEmpty(album) is no
Related
Sub route appending empty record to collection I've got a bit of a tricky problem and I'm hoping you peeps can help.
This works as expected BUT if I refresh the page with a location sub route the locations list gets an empty record appended to the end.
App.Router.map ->
this.resource 'home', { path: '/' }
this.resource 'locations', ->
this.resource 'location', { path: ':slug' }
this.resource 'services'
this.resource 'contact'
this.resource 'login'
App.LocationsRoute = Ember.Route.extend
model: ->
this.store.find 'location'
App.LocationRoute = Ember.Route.extend
serialize: (model, params)->
slug: model.get 'slug'
model: (params)->
this.store.find 'location', params.slug
Any help greatly appreciated
I have a select box with a list of users that I get from the store. I have a method on the controller where I try to get an initial user for the selectbox. No matter what I do I can't seem to get any user record to resolve on the method but the users show up fine in the selectbox. Can someone explain what I'm missing? Thank you in advance for the help.
Controller:
App.TodoModuleController = Ember.ObjectController.extend
users: Em.computed -> #store.findAll 'user'
selectedUser: Em.computed 'users', ->
#get('users').objectAt(1)
# There are 4 users in the db. Just using 1 for a test.
# I also tried
# #get('users').then (users)->
# users.objectAt(1)
selectedUserDidChange: Em.observer 'selectedUser', ->
if #get 'selectedUser' then #assignUser()
assignUser: ->
model = #get 'model'
model.set 'assigneeId', #get('selectedUser').get('id')
unless model.save()
console.log 'Error: TodoModuleController.assignUser'
Template:
{{view Em.Select content=users selection=selectedUser optionValuePath='content.id' optionLabelPath='content.firstName'}}
SOLUTION (thanks to Hrishi):
Todo Model:
App.Todo = DS.Model.extend
text: DS.attr 'string'
assignee: DS.belongsTo 'user', inverse: null
Todo Controller:
App.TodoModuleController = Ember.ObjectController.extend
users: Em.computed -> #store.findAll 'user'
assignedUserDidChange: Em.observer 'assignee', ->
if #get 'assignee' then #assignNewUser()
assignNewUser: ->
unless #get('model').save()
console.log 'Error: TodoModuleController.assignUser'
Select Box:
{{view Em.Select content=users selection=assignee optionValuePath='content.id' optionLabelPath='content.firstName'}}
Computed properties are not computed until someone (in your case, the template) tries to access them, in other words, they are computed lazily. Since the template tries to access them, the users array will get populated and you can see it on the page when you click on your select box. The way I would do this would be to put an attribute on the model called assignee and bind the view's selection directly to that.
The Ember.js application
# routes/application.js.coffee
########################################
App.ApplicationRoute = Ember.Route.extend
model: ->
#store.findAll('category').then (records) ->
{
categories: records
}
# routes/categories.js.coffee
########################################
App.CategoriesRoute = Ember.Route.extend
model: ->
#store.find 'category'
# routes/category.js.coffee
########################################
App.CategoryRoute = Ember.Route.extend
model: (params) ->
serialize: (model, params) ->
id: model.get('slug')
# templates/application.hbs
########################################
{{ partial 'categories' }}
<p>---</p>
{{ outlet }}
# templates/categories.hbs
########################################
<h1>Categories...</h1>
{{#each category in categories}}
{{#link-to 'category' category}}
{{category.title}}
{{/link-to}}
{{/each}}
# templates/category.hbs
########################################
<h2>{{title}}</h2>
<h3>{{description}}</h3>
# router.js.coffee
########################################
App.Router.map ->
#resource 'categories', path: 'categories'
#resource 'category', path: 'category/:slug'
# store.js.coffee
########################################
App.ApplicationAdapter = DS.ActiveModelAdapter.extend
namespace: 'api/v1'
What I am trying to accomplish
I am loading Category on the Application route so the data can be used to render the site-wide navigation via the categories partial.
Model is acquired successfully and stored, according to the Ember console. If it makes any difference, one-to-many data is being sideloaded, called Sections, which is also stored successfully.
The category partial is rendered as expected, with links to each section. Clicking on them yields the rendering of the title and description.
What is wrong
Refreshing the application on the route of say, /#/category/title-1, doesn't render the category view (both title and description). However, clicking on the links generated in the categories partial will render the view.
What I expect on page load is the rendering of the category view, without the need of clicking on the categories links. What am I doing wrong?
After playing around with the Application for too long, I figured out a solution to my problem.
When using the Ember console, I saw that the model for the Category view was referenced to [Object object] and not App.Category. I had to specify the store to search by the slug. Therefore, the code looks like this
# routes/category.js.coffee
########################################
App.CategoryRoute = Ember.Route.extend
model: (params) ->
serialize: (model, params) ->
id: model.get('slug')
#store.find('category', params.slug)
The view is now rendered on page load.
I want to use the information already received within a linked template. Nesting routes has created a whole heap of errors, and I'm a little lost on how to pass this data, but it seems like it must be possible?
This works, but strikes me as a poor hack. Ideally I'd only want one API round-trip...
App.Router.map ->
#resource 'photos'
#route 'photo', path: 'photo/:photo_id'
App.PhotosRoute = Ember.Route.extend
model: ->
Ember.$.getJSON('http://api.flickr.com/services/feeds/photos_public.gne?tags=cake&tagmode=all&format=json&jsoncallback=?')
setupController: (controller,model) ->
controller.set 'photos', model.items.map (i) ->
i.id = model.items.indexOf(i)
App.PhotoRoute = Ember.Route.extend
model: (params) ->
jQuery.getJSON('http://api.flickr.com/services/feeds/photos_public.gne?tags=cake&tagmode=all&format=json&jsoncallback=?').then (api) ->
api.items[params.photo_id]
App.PhotosController = Ember.ObjectController.extend
itemController: 'photo'
{{#linkTo 'photo' this }}<img {{bindAttr src="media.m"}} />{{/linkTo}}
You can use the modelFor(routeName) to get the model from some route. In your case probally you will fetch all data in PhotosRoute, and want to reuse it. You can use this in your PhotoRoute:
App.PhotoRoute = Ember.Route.extend
model: (params) ->
#modelFor('photos').items[params.photo_id]
So just one api call will be done.
I thought I had a fairly simple solution to find models with attributes other than ID, but I'm running into one problem.
Current setup:
Ember Router:
App.Router.map ->
#resource "posts", ->
#route "show", {path: ':slug'}
App.PostsShowRoute = Ember.Route.extend
serialize: (model, params) ->
object = {}
name = params[0]
object[name] = model.get('slug')
return object
model: (params) -> App.Post.find(params.slug)
Rails Controller:
class PostsController < ApplicationController
def show
#post = Post.find_by_slug(params[:id])
render json: #post
end
end
THE PROBLEM
If params.slug == "some-post", when post object is returned from the server, post.id == "some-post". This messes up all the associations.
This is probably because DS.Store is assuming that if I call find(something), something is the id. I would have expected that the response from the server would overwrite this assumption, but it doesn't.
Is there a better way to do this? My use case is extremely simple. All I need to do is serialize and deserialize a post object by the slug attribute.
I'm using Ember Data revision 11
The solution turned out to be findQuery. I was using this some time ago, but I didn't know how to make use of the promise.
model: (params) ->
#get('store').findQuery(App.Post, {slug: params.slug}).then (data) ->
return data.get('firstObject')
and on the rails side:
class PostsController < ApplicationController
def index
#posts = params[:slug] ? Post.where(slug: params[:slug]) : Post.homepage
render json: #posts
end