Reputation: 90
Embsters!
I am trying to figure out why my model isn't refreshed after I create a new record and save it to the store.
My route computes the model
as follows:
model: function (params) {
var postID = params.post_id,
userID = this.get('session.currentUser.id');
var post = this.store.findRecord('post', postID) ;
var followings = this.store.query('post-following', {
filter: { post: postID }
}) ;
var userFollowing = this.store.queryRecord('post-following', {
filter: { post: postID, user: userID }
}) ;
return new Ember.RSVP.hash({
post: post,
followings: followings,
userFollowing: userFollowing
});
}
My template then renders a list and a button:
{{#each model.followings as |following|}}
...
{{/each}}
{{#if model.userFollowing}}
<button {{action 'follow'}}>Follow</button>
{{else}}
<button {{action 'unFollow'}}>Unfollow</button>
{{/if}}
And my controller creates/deletes the relevant post-following
record:
actions: {
follow: function () {
var user = this.get('session.currentUser'),
post = this.get('model.post') ;
this.store.createRecord('post-following', {
user: user,
post: post
}).save();
},
unFollow: function () {
this.get('model.userFollowing').destroyRecord() ;
}
}
When I click the [Follow]
button:
POST
request is sentWhen I (refresh the page then) click the [Unfollow]
button:
DELETE
request is sentDo you have any idea of what I'm doing wrong?
Could it be a problem with my payload?
Well, it sounds like I was expecting too much from ember.
The framework won't automatically update my post-following
s array on store.createRecord('post-following', {...})
call.
I then adjusted my controller logic to "manually" update my model:
// in follow action…
userFollowing.save().then( function(){
var followings = store.query('post-following', {
filter: { post: postID }
}).then( function (followings) {
_this.set('model.userFollowing', userFollowing);
_this.set('model.followings', followings);
}) ;
});
// in unFollow action…
userFollowing.destroyRecord().then( function () {
_this.set('model.userFollowing', null);
_this.notifyPropertyChange('model.followings') ;
});
Please note that my backend API design has been criticized by @duizendnegen (see comments). More best practices in this article.
Thanks you for all your help !!!
Brou
Upvotes: 2
Views: 765
Reputation: 35481
Your issue is that you aren't re-setting the property model
to point to the newly created object. You are always accessing the same model
property, even after creating a new one.
First thing to be aware of is that, after the model
hook in your route, the setupController
hook is called that executes:
controller.set('model', resolvedModel)
meaning that the model
property on your controller is, by default, set every time the route loads (the model
hook resolves). However, this doesn't happen after you create a new record so you must do it explicitly:
let newModel = this.store.createRecord('post-following', {
user: user,
post: post
})
// since model.save() returns a promise
// we wait for a successfull save before
// re-setting the `model` property
newModel.save().then(() => {
this.set('model', newModel);
});
For a more clear design, I would also recommend that you create an alias to the model
property that more specifically describes your model or override the default behavior of setupController
if you are also doing some initial setup on the controller. So either:
export default Ember.Controller.extend({
// ...
blog: Ember.computed.alias('model') // more descriptive model name
// ...
});
Or:
export default Ember.Route.extend({
// ...
setupController(controller, resolvedModel) {
controller.set('blog', resolvedModel); // more descriptive model name
// do other setup
}
// ...
});
Upvotes: 1
Reputation: 73
For these kind of questions, it really helps to have a smaller, replicated problem (e.g. through Ember Twiddle)
Fundamentally, the new post-following
record doesn't match the filter
: it is filtered for an attribute { post: 123 }
and your post-following
object contains something in the lines of { post: { id: 123, name: "" } }
. Moreover, your post-following
object doesn't contain a property called filter
or what it could be - i.e. the query it executes to the server are different than those you want to filter by on the client.
My approach here would be to, as a response to the follow
and unfollow
actions, update the model
, both the userFollowing
and followings
.
Upvotes: 1
Reputation: 392
Your model is set when you enter the page. When changes are made, your model doesn't change. The only reason why the list is updated when you destroy the record is because it simply doesn't exist anymore. Reload the model after clicking the follow button or unfollow button, or manually change the values for the list/button.
Upvotes: 0