I have a route that displays a list of challenges, when I create a new challenge the record is persisted however the model of list of challenges is not updated when I transition back into the route. Is there something I am missing?
//new.js
var challenge = this.store.createRecord('challenge', {
name_en: this.get('model.name_en'),
name_fr: this.get('model.name_fr'),
description_en: this.get('model.description_en'),
description_fr: this.get('model.description_fr'),
end_date: this.get('model.end_date'),
start_date: this.get('model.start_date'),
points_cap: this.get('model.points_cap'),
points_goal: this.get('model.points_goal'),
challenge_type: 1,
short_description_en: this.get('model.short_description_en'),
short_description_fr: this.get('model.short_description_fr'),
excluded_activities: excluded
});
// Persist record.
challenge.save().then((challenge) => {
this.transitionToRoute('challenges');
}).catch((error) => {
this.handleError(error, 'error.system_error');
});
//router.js
Router.map(function() {
this.route('challenges', function() {
this.route('new');
this.route('challenge', {
path: ':challenge_id'
}, function() {
this.route('delete');
this.route('edit');
});
});
//challenges.js
import Ember from 'ember';
import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';
import UserProfile from '../models/user-profile';
export default Ember.Route.extend(AuthenticatedRouteMixin,{
userProfile: UserProfile.create(),
model: function() {
return this.store.query('challenge', {league_id: this.get('userProfile.league_id')});
}
});
//new challenge payload
{
"activity_exclusion_list":[
],
"challenge_type":1,
"challengeUrl":null,
"end_date":"31-10-2015",
"number_participants":null,
"number_teams":null,
"points_cap":null,
"points_goal":null,
"start_date":"01-10-2015",
"leagueId":"1",
"teams":[
],
"name_lang":{
"en":"New Challenge ",
"fr":null
},
"description_lang":{
"en":"New Challenge",
"fr":null
},
"short_description_lang":{
"en":"New Challenge",
"fr":null
}
}
//response from new challenge
{
"challenge_type":"Individual",
"description":" ",
"description_fr":null,
"description_lang":{
"en":"New Challenge",
"fr":null
},
"challengeUrl":" ",
"start_date":"01-10-2015",
"end_date":"31-10-2015",
"name":" ",
"name_fr":null,
"name_lang":{
"en":"New Challenge ",
"fr":null
},
"points_cap":0,
"points_goal":0,
"short_description":" ",
"short_description_fr":null,
"short_description_lang":{
"en":"New Challenge",
"fr":null
},
"number_participants":0,
"number_teams":0,
"teams":[
],
"challenge_id":265,
"activity_exclusion_list":[
],
"leagueId":1
}
In your challenges route have you tried using a this.store.filter instead? The issue could be that the query function only returns a RecordArray, whereas filter returns a Live RecordArray which will update your templates and everything else when the promise (in this case the successful save) is resolved.
model: function() {
return this.store.filter('challenge', {league_id: this.get('userProfile.league_id')}, function() {
// We're not actually filtering, so just return true for everything
return true;
});
}
I had the same problem and this turned out to be the solution, hope it helps!
Ember Docs reference
Related
I have some problem with get data from storage.
Isset model orders:
import DS from 'ember-data';
export default DS.Model.extend({
test: DS.hasMany('dealer-status'),
});
adapter (its is test data). I havn't normolize responce and i add params to data for normalize. It is implementation will be in serialize :
export default DS.JSONAPIAdapter.extend({
service: Ember.inject.service('admin.auth'),
query(store, type, query) {
var service = this.get('service');
return new Ember.RSVP.Promise(function (resolve, reject) {
service.fetch(query).subscribe(
res => {
var data = {
"data": [{
"type": "user",
"id": "1",
"attributes": {
test: 'test'
}
}]
};
resolve(data);
},
err => {
reject(err);
});
});
}
});
The router:
model() {
return this.get('store').query('orders', {}).then(res => {
console.log(res.get('test')); //undefined
console.log(res.objectsAt(0)); //undefined
})
In router I find by query, but i can't get param test. In Promise res.get('test') return undefined.
Why i get undefined in promise? How fix it?
Because in your order model you don't have attribute test. It's a hasMany relationship. Look into json API documentation about relationships in resource objects for more details.
Sorry if this question is too naive,but I am getting confused a lot on rendering views in Ember.
I have a 'Person' route. I am able to do CRUD operations on it.
router.js
this.route('person', function() {
this.route('index', { path: '' });
});
controllers/person/index.js
actions: {
createPerson: function() {
var person = this.get('store').createRecord('person');
this.set('person', person);
this.set('editPersonPane', true);
},
editPerson: function(person) {
this.set('person', person);
this.set('editPersonPane', true);
},
closeEditPerson: function() {
this.get('person').rollback();
this.set('editPersonPane', false);
},
savePerson: function(person) {
var _this = this;
person.save().then(function() {
_this.set('editPersonPane', false);
Ember.get(_this, 'flashMessages').success('person.flash.personUpdateSuccessful');
}, function() {
Ember.get(_this, 'flashMessages').danger('apiFailure');
});
},
deletePerson: function(person) {
var _this = this;
person.destroyRecord().then(function() {
_this.set('editPersonPane', false);
Ember.get(_this, 'flashMessages').success('person.flash.personDeleteSuccessful');
}, function() {
Ember.get(_this, 'flashMessages').danger('apiFailure');
});
}
}
What I want to do now is when I want to create a new person, a form slides in to create it. After filling up the form, I want the list view of persons to be updated immediately, without refreshing the page. Right now, I have been able to add the form and when I add a new person, I get a successful flash message but it's not updated in the view immediately. I have to refresh the page.
It might have to do something with observers but I am still not sure how.
Reloading a saved object will allow you to avoid having to refresh the page:
savePerson: function(person) {
var _this = this;
person.save().then(function(saved) {
saved.reload();
_this.set('editPersonPane', false);
Ember.get(_this, 'flashMessages').success('person.flash.personUpdateSuccessful');
}, function() {
Ember.get(_this, 'flashMessages').danger('apiFailure');
});
}
Also, it's worth noting that if you destructure and use ES6 syntax, you can clean up your code a bit as follows:
//controllers/person/index.js
//at the top of the file
import Ember from 'ember';
const { get, set } = Ember;
//other code
actions: {
//other actions
savePerson(person): {
person.save().then((saved) => {
saved.reload();
set(this, 'editPersonPane', false);
get(this, 'flashMessages').success('person.flash.personUpdateSuccessful');
}, () {
get(this, 'flashMessages').danger('apiFailure');
});
}
}
Which route is displaying your persons list?
Wouldn't something like this work better, so you can display the list and then edit a person within the persons.hbs outlet?
this.route('persons', function() {
this.route('person', { path: 'id' });
});
So, I'm trying to use the Twitter-style URL syntax, allowing a user to go to example.com/quaunaut to visit the user page of the user with the username 'quaunaut'. I was able to accomplish this via:
app/router.js
export default Router.map(function() {
this.route('users.show', { path: '/:user_username' });
});
app/routes/users/show.js
export default Ember.Route.extend({
model: function(params) {
return this.store.find('user', { username: params.user_username }).then(function(result) {
return result.get('firstObject');
});
},
serialize: function(model) {
return { user_username: model.get('username') };
}
});
Now, when live or run via ember s, this works fantastically. However, in tests, it seems for some reason to not resolve.
var application, server, USERS;
USERS = {
'example1': [{
id: 1,
username: 'example1'
}],
'example2': [{
id: 2,
username: 'example2'
}]
};
module('Acceptance: UsersShow', {
beforeEach: function() {
application = startApp();
server = new Pretender(function() {
this.get('/api/users', function(request) {
return [
201,
{ 'content-type': 'application/javascript' },
JSON.stringify(USERS[request.queryParams.username])
];
});
});
},
afterEach: function() {
Ember.run(application, 'destroy');
server.shutdown();
}
});
test('visiting users.show route', function(assert) {
visit('/example1');
andThen(function() {
assert.equal(currentPath(), 'users.show');
assert.equal(find('#username').text(), 'example1');
});
});
Which results in the following test results:
Acceptance: UsersShow: visiting users.show route
✘ failed
expected users.show
✘ failed
expected example1
So, any ideas why currentPath() isn't resolving? If you also have any recommendations for better means to implement what I'm looking to do here, I'm certainly open to it.
Your visit syntax isn't quite right, should be:
test('visiting users.show route', function(assert) {
visit('/example1').then(function() {
assert.equal(currentPath(), 'users.show');
assert.equal(find('#username').text(), 'example1');
});
});
Is this possible? I know I can do:
this.store.find('model', 1)
but that's not what I want. I would like to retrieve the json in this format: (working if I retrieve it in the route like this ):
App.OptionsRoute = Ember.Route.extend({
model: function () {
return {
"options":{
"id": "1",
"headline": "A Headline",
"results": [
{
"id": "1",
"title": 'Option 1',
},
{
"id": "2",
"title": "Option 2"
}
]
}
};
}
});
options model:
App.Options = DS.Model.extend({
headline: DS.attr(),
results: DS.attr()
});
options.hbs
<h5>{{options.headline}}</h5>
{{#each item in options.results}}
<h5>{{item.title}}</h5>
{{/each}}
I am using the RESTAdapter. And that is the only model that will be retrieved on that route. I would like to be able to use ember-data, but store.find expects an array.
You're missing a point here. First of all you're using bad format for your response. You need custom serializer. You can also use a bit more dirty workaround like this(but it works). Route:
App.OptionsRoute = Ember.Route.extend({
model: function() {
that = this;
return new Promise(function (resolve, reject) {
url = that.store.adapterFor('option').buildURL('option');
Ember.$.getJSON(url).then(function (json) {
body = json.options;
correct = {
options: [
body
]
};
that.store.pushPayload('option', correct);
resolve(that.store.all('option').get('firstObject'));
});
});
}
});
Template:
<h5>{{model.headline}}</h5>
{{#each item in model.results}}
<h5>{{item.title}}</h5>
{{/each}}
Application outputs:
A Headline
Option 1
Option 2
Working demo - please notice that I'm using $.mockjax to recreate your response from server, but it matches format you provided.
Following this post, the scenario is the same outlined here, i.e. a list of posts, each having zero or more comments.
Suppose one has the following router.
App.Router.map(function() {
this.resource('posts', function() {
this.resource('post', { path: '/:post_id' }, function() {
this.resource('comments', function() {
this.route('create');
});
});
});
});
The model for a post is the following one.
App.Post = DS.Model.extend({
title: DS.attr('string'),
comments: DS.hasMany('comment', { async: true })
});
A post, for example, is the following one.
{
"post": {
"id": 1,
"title": "Rails is omakase",
"links": { "comments": "/posts/1/comments" }
}
}
This way, I am able to load the comments of this post using the following route.
App.CommentsRoute = Ember.Route.extend({
model: function() {
return this.modelFor('post').get('comments');
}
});
The question now is: how can I create the CommentsCreateRoute, so that the new comment is actually posted to /posts/1/comments and not to /comments?
So far I have the following.
App.CommentsCreateRoute = Ember.Route.extend({
model: function() {
var newComment = this.store.createRecord('comment');
newComment.set('title', 'test comment');
return newComment;
}
});
App.CommentsCreateController = Ember.ObjectController.extend({
actions: {
saveEditing: function(){
var newComment = this.get('model');
newComment.save().then(function(comment) {
/* OK saved */
}, function(response) {
/* show errors */
});
}
}
});
Does this REST scheme make sense?
GET /posts/{post_id}/comments
PUT /posts/{post_id}/comments/{comment_id}
POST /posts/{post_id}/comments
or should I use the following?
GET /posts/{post_id}/comments
PUT /comments/{comment_id}
POST /comments
or any other? Which would be the most "standard"?