How to properly get hasMany model in route - ember.js

I have 2 models Post and Comment. Both have own routes: PostRoute and PostCommentsRoute, in the first case I simply use #store.find to load model data but I have a problem with the second route. When I try to refer to Post and then get its comments, they loads but don't update when I add new one. If I use #store.find 'comment', it stays updated however loads everything, so it's not the point. How to get only comments related to the post and keep them updated?
App.Post = DS.Model.extend
comments: DS.hasMany 'comment', async: true
App.Comment = DS.Model.extend
post: DS.belongsTo 'post'
text: DS.attr 'string'
App.Router.map ()->
#resource 'post', path: '/post/:post_id', ()->
#route 'comments'
App.PostCommentsController = Em.ArrayController.extend
newComment: ""
needs: 'post'
post: Em.computed.alias 'controllers.post'
sortProperties: ['created'],
sortAscending: false
actions:
addComment: ()->
commentText = #get 'newComment'
post = #get 'post'
comment = #store.createRecord 'comment',
text: commentText
post: post.get 'content'
#set 'newComment', ''
comment.save()
App.PostRoute = Em.Route.extend
model: (params)->
#store.find 'post', params.post_id
App.PostCommentsRoute = Em.Route.extend
model: (params)->
# loads only comments to parent post but doesn't update
post = #modelFor 'post'
post.get 'comments' # /api/posts/1/comments
App.PostCommentsRoute = Em.Route.extend
model: (params)->
# updates but loads all comments
#store.find 'comment' # /api/comments

After you save your comment you have to push it on the post's comments:
comment.save().then(function () {
post.get('comments').push(comment);
// or if that doesn't work you may need to resolve the promise:
post.get('comments').then(function (comments) {
comments.push(comment);
});
});

Related

Ember - Querying model by properties in a related model

I'm trying query my post model for published posts that have a specific tag. My models look like this:
var Post = DS.Model.extend({
tags: DS.hasMany('tag', { async: true }),
title: DS.attr('string'),
published: DS.attr('boolean'),
});
var Tag = DS.Model.extend({
posts: DS.hasMany('post', { async: true }),
name: DS.attr('string')
});
I've been able to get published posts in my query using the find() method:
this.get('store').find('post', {published: true});
But I don't understand how to query for properties that are part of a related model. I'd appreciate any guidance, thanks!
Edit
I came up with this solution using filter() which seems to work well.
var self = this;
var store = this.get('store');
store.find('post', {published: true}).then(function() {
self.set('content', store.filter('post', function(post) {
return post.get('tag.name') === 'Photography';
}));
});

Ember sub route appending empty record to collection

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

Ember Uncaught Error: Attempted to handle event `didSetProperty`

I am getting this error and it seems to be when I destroy the session on my "auth" logic. I have read everything I can find and it seems to be something to do with the values of the object that is being destroyed, but I've tried everything I have found and no luck. If anyone could point me in the right direction to a solution I would greatly appreciate it.
Error
Uncaught Error: Attempted to handle event didSetProperty on while in state root.deleted.saved. Called with {name: email, oldValue: undefined, originalValue: undefined, value: test#test.com}.
Controller
App.ApplicationController = Ember.ObjectController.extend
actions:
signOut: ->
#get('model').destroyRecord().then =>
$.removeCookie 'apiKey'
#set 'model', #store.createRecord 'session'
#transitionToRoute 'sign-in'
, ->
#transitionToRoute 'sign-in'
Route
App.ApplicationRoute = Ember.Route.extend
model: ->
if !$.cookie 'apiKey'
#store.createRecord 'session'
else
#store.find('session', 'current').then (session)->
session
Session Model
App.Session = DS.Model.extend
access_token: DS.attr()
email: DS.attr()
password: DS.attr()
isLoggedIn: Ember.computed.notEmpty 'access_token'
user: DS.belongsTo 'user', embedded: 'always'
App.SessionSerializer = DS.ActiveModelSerializer.extend DS.EmbeddedRecordsMixin,
attrs: user: embedded: 'always'
This is a bit late, sorry.
When the promise to destroy the model is resolved, something is being set on the model - session record in this case. Please note the #get('model').destroyRecord() command is followed by the #set 'model' command.
That is why the error message has while in state root.deleted.saved.

Pass a preset into a create controller

In my app, there are Templates and Documents. I want to be able to create a document from a template, i.e. the user will be able to go to the template show page, click a button, and be redirected to the new document page, with document text pre-filled from the template (I only need to have the text pre-filled, I don't care about the document knowing the template it's made from).
But how would I pass the text to the new document page?
I ended up doing the following:
App.Router.map ->
#resource 'documents', ->
#route 'new'
#route 'new_from_template', path: '/new/:template_id'
App.DocumentsNewFromTemplateRoute = Ember.Route.extend
model: (params) ->
model = App.Document.createRecord()
if params.template_id
App.Template.find(params.template_id).then (template) ->
model.set 'text', template.get('text')
model
setupController: (controller, model) ->
if model._reference.type == App.Template
model = #model(template_id: model.id)
#currentModel = model
#controllerFor('documentsNew').set 'model', model
renderTemplate: ->
#render 'documents/new'
And to link to new document form for template, I simply do
{{#linkTo 'documents.new_from_template' template}}Create a document{{/linkTo}}
You can define an action in the controller:
App.TemplateRoute = Em.Route.extend({
model: function() {
return Em.Object.create({
name: "A Template",
values: {title: "Templated Title"}
});
}
});
App.TemplateController = Em.ObjectController.extend({
goToNewDocument: function() {
var o = Em.Object.create(this.get('values'));
o.set('source', 'Template');
App.Router.router.transitionTo('newdoc', o);
}
});
App.NewdocRoute = Em.Route.extend({
model: function() {
return Em.Object.create({title: "Default Title", source: "Model hook"});
}
});
jsbin demo

Can't find nested url: no route matched URL

Ember shows me the following error: Uncaught Error: No route matched the URL '/users'
Sks.IndexRoute = Ember.Route.extend
redirect: ->
this.transitionTo 'users'
Sks.Router.map ->
this.resource 'users', path: 'users/:user_id'
Sks.UsersRoute = Ember.Route.extend
setupController: (controller, model) ->
this.controllerFor('users').set 'content', Sks.User.find()
this.controllerFor('currentUser').set 'content', Sks.CurrentUser.find 1
this.controllerFor('top').set 'content', Sks.Top.find()
this.controllerFor('hamsters').set 'content', Sks.Hamster.find()
Everything works when I remove the dynamic segment.
Version: v1.0.0-rc.1-78-gd4e6a5c
edit#1
added IndexRoute
In Ember, collections and items actually use separate routes. Here's how I do it:
App.Router.map(function () {
this.resource('contacts', { path: '/contacts' });
this.resource('contact', { path: '/contact/:contact_id' });
});
App.IndexRoute = Ember.Route.extend({
redirect: function () {
this.replaceWith('contacts');
}
});
App.ContactsRoute = Ember.Route.extend({
model: function (params) {
return App.Contact.find();
}
});
App.ContactRoute = Ember.Route.extend({
model: function (params) {
return App.Contact.find(params.contact_id);
}
});
Here's a working jsFiddle.
It seems that I should have RTM :)
Sks.Router.map ->
this.resource 'users', ->
this.resource 'user', path: ':user_id'