Generally, Ember HasMany relationship json format is follow,
{ "post" : { id:1, title:"this is title", comments:[1,2], writer: ...} }
But, i want to use next json format (because, my server return like this)
{ "post" : { id:1, title:"this is title",
comments:[
{id:1, bodytext:"blarblar...."},
{id:2, bodytext:"second blarblar...."},
], writer: ...} }
How can I use this?
Isn't there any problem in ember store relationship?
This is a job for EmbeddedRecordsMixin.
If you're implementing the server yourself and it's purpose-built for your ember application, you should consider switching to side-loading instead:
{ "post" : { id: 1,
title: "this is title",
comments: [1,2],
writer: ...
},
"comments": [ { id: 1,
bodytext: "blarblar...."
},
{ id: 2,
bodytext: "second blarblar...."
}
]
}
That way, it would be still just one request, but would work for more complicated structures (other than trees) as well.
Related
I am working with Ember and Ember-data. But the JSON which i receive is not par with the Ember side-loading standards. The JSON does'nt have a root model. Also the models are embedded and some times haves Ids and sometimes does not have Id.
I have seen couple of links on how to add root model using extract hook and also how to play with embedded model using
App.ColorSerializer = DS.RestSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
foos: {embedded: 'always'}
}
});
This code is taken from this link.
This is the JSON used there
{
colors:[
{
id: 1,
color: "red",
foos:[
{
id:1,
name:'something 1'
},
{
id:2,
name:'something 2'
}
]
},
...
Now the problem that i am facing is that my JSON could also look like below(no root model "color")
{
id: 1,
color: "red",
foos:[
{
id:1,
name:'something 1'
},
{
id:2,
name:'something 2'
}
]
},
...
or even like this(without Ids for foo objects)
{
id: 1,
color: "red",
foos:[
{
name:'something 1'
},
{
name:'something 2'
}
]
},
...
Is there any way i can handle this? How do i add Ids to the embedded model foo? Also is there some solution/plugin which would accept any kind of embedded JSON and convert it into side loaded JSON and added Ids if needed.
I have seen this solution. Does it really work? Because it does not use the latest EmbeddedRecordsMixin
I used a generic transform for arrays:
// /transforms/array.js
import DS from "ember-data";
import Ember from "ember";
export default DS.Transform.extend({
deserialize: function (value) {
if (Ember.isArray(value)) {
return Ember.A(value);
} else {
return Ember.A();
}
},
serialize: function (value) {
if (Ember.isArray(value)) {
return Ember.A(value);
} else {
return Ember.A();
}
}
});
Then in my model, I simply use:
foos: DS.attr("array")
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.
I have a model like:
var Survey = DS.Model.extend({
title: DS.attr('string'),
});
and:
var SurveySection = DS.Model.extend({
survey: DS.belongsTo('survey', {async:true}),
title: DS.attr('string'),
help_text: DS.attr('string'),
});
If i have a survey object, can I just do survey.get('survey_section') to get all the sections associated with a particular survey, because this isn't working? It doesn't even work if I add a survey_sections: DS.hasMany('survey_sections', {async:true}) to my survey model.
I should add that I'm using fixtures. When I release the app they'll still be used (ie so if the RESTAdapater would fix it, that's not a fix in my case):
Survey.reopenClass({
FIXTURES: [
{
"id": 1,
"title": "Favourite food"
},
{
"id": 2,
"title": "Sports"
}
]
});
and:
SurveySection.reopenClass({
FIXTURES: [
{
"help_text": "",
"id": 1,
"survey": 1,
"title": "Italian food"
},
{
"help_text": "",
"id": 2,
"survey": 1,
"title": "Team sports"
}, ...]});
Is the fixture adapter not able to retrieve related records in the reverse direction like this? If not, will I have to go the laborious route of manually getting the sections with survey=1, for example (laborious because I'll have to take this approach throughout my whole app with other models)?
Update
Specifically my failing code is (with survey 1):
this.get('survey').get('survey_sections').then(function(survey_sections) {
// survey_sections contains no objects, so objectAt(0) returns undefined.
survey_sections.objectAt(0).get('questions').then(function(questions) {
console.log('Set first question ID to ' + self.get('firstQuestionId'));
});
});
As the fixtures show there should be 2 SurveySection objects in survey_sections, but instead none are found.
I didn't want to do it, but I had to add the forward relation to the items in the Survey fixture, e.g.:
Survey.reopenClass({
FIXTURES: [
{
"id": 1,
"title": "Favourite food",
"survey_sections": [1, 2],
},
{
"id": 2,
"title": "Sports",
"survey_sections": [3],
}
]
});
and update the Survey model with:
survey_sections: DS.hasMany('survey_sections', {async:true})
My backend replies to find all requests:
User.find();
Like this
{ 'users' : [ user1_obj, user2_obj ] }
Ember-data is happy about it. Now if I do a simple single object find:
User.find('user1');
I have tried configuring the backend to return any of the following:
user1
{ 'user1' : user1_obj }
{ 'user' : { 'user1' : user1_obj } }
{ 'user' : user1_obj }
But none of those are working. What should I return from the backend in reply to find("obj-id") requests? According to the documentation about JSON ROOT, the right format looks like:
{ 'user' : user1_obj }
Ember does not complain about it, but the Ember Objects processed have a very strange structure, like this:
As you can see, _reference.record is referring to the top record. Also (not shown here) _data field is empty.
What could be causing that strange nesting?
EDIT
As linked by mavilein in his answer, the JSON API suggests using a different format for singular resources:
{ 'users' : [user1_obj] }
That means, the same format as for plural resources. Not sure if Ember will swallow that, I'll check now.
Following this specification, i would suspect the following:
{
'users' : [{
"id": "1",
"name" : "John Doe"
},{
"id": "2",
"name" : "Jane Doe"
}]
}
For singular resources the specification says:
Singular resources are represented as JSON objects. However, they are
still wrapped inside an array:
{
'users' : [{
"id": "1",
"name" : "John Doe"
}]
}
Using User.find() will expect the rootKey pluralized and in your content an array of elements, the response format is the following json:
{
users: [
{ id: 1, name: 'Kris' },
{ id: 2, name: 'Luke' },
{ id: 3, name: 'Formerly Alex' }
]
}
And with User.find(1) the rootKey in singular, and just one object:
{
user: {
id: 1, name: 'Kris'
}
}
Here a demo showing this working
I was working on a code which was about integrating ExtJS 4 and Django. The link is:
https://github.com/diegocmsantos/extjs4-tdc2011-django
It works fine on ExtJS 4.0.0. But when I upgrade to 4.1.0 it's proxy returns update api instead of create.
I have added the 'idProperty' parameter to the Model, but still gives me the same result.
Model class:
Ext.define('TDC2011.model.Contact', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields : [
{ name : "id", type : "int", mapping : "#id" },
{ name : "name", type : "string"},
{ name : "phone", type : "string"},
{ name : "email", type : "string"}]
});
Store Class:
Ext.define('TDC2011.store.Contacts', {
extend: 'Ext.data.Store',
model: 'TDC2011.model.Contact',
autoLoad: true,
pageSize: 35,
autoLoad: {start: 0, limit: 35},
proxy: {
type: 'ajax',
api: {
read : 'contact/view.action',
create : 'contact/create.action/',
update: 'contact/update.action/',
destroy: 'contact/delete.action/'
},
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: false,
root: 'data'
},
listeners: {
exception: function(proxy, response, operation){
Ext.MessageBox.show({
title: 'REMOTE EXCEPTION',
msg: operation.getError(),
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
});
Is there anyone who knows the main cause of problem?