I have a REST endpoint "http://localhost:8080/customers" which I would like to hook to my Ember JS app.
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.extend({
url: 'http://localhost:8080/customers'
})
});
REST Payload
{
"_links" : {
"search" : {
"href" : "http://localhost:8080/customers/search"
}
},
"_embedded" : {
"customers" : [ {
"id" : 2,
"firstName" : "Jim",
"lastName" : "Smith",
"_links" : {
"self" : {
"href" : "http://localhost:8080/customers/2"
}
}
}, {
"id" : 1,
"firstName" : "Jimmy",
"lastName" : "Jones",
"_links" : {
"self" : {
"href" : "http://localhost:8080/customers/1"
}
}
} ]
}
}
I keep on getting this error. This is my second week on Ember JS. To be honest this is a lot harder than I imagined. Not very easy to debug or understand.
Error while loading route:
TypeError: undefined is not a function
at App.CustomersRoute.Ember.Route.extend.model
Essentially you need to transform your data into this format using a custom serializer:
{
"customers" : [
{
"id" : 2,
"firstName" : "Jim",
"lastName" : "Smith"
}, {
"id" : 1,
"firstName" : "Jimmy",
"lastName" : "Jones"
}
]
}
You'll want to read https://github.com/emberjs/data/blob/master/TRANSITION.md which explains how to use extractSingle, extractArray, normalize, normalizeHash.
You're particular example looks close to the api's example:
http://emberjs.com/api/data/classes/DS.RESTSerializer.html#method_extractArray
App.CustomerSerializer = DS.ActiveModelSerializer.extend({
extractArray: function(store, type, payload) {
// do your own implementation and return that, or modify it slightly
// and do the default implementation
return this._super(store, type, payload);
},
});
Related
Is there any way to define arrays on EmberJS models? I saw some posts using Transformation but those approaches don't achieve the results I need.
This is the (json) model I'm trying to represent:
{
"category" : "Category 1",
"subcategories" : [
{
"name" : "subcategory1",
"value" : 210
},
{
"name" : "subcategory2",
"value" : 220
}
]
},
{
"category" : "Category 2",
"subcategories" : [
{
"name" : "subcategory21",
"value" : 250
},
{
"name" : "subcategory22",
"value" : 270
}
]
}
I read about the hasMany method but I understand that it's only for relationships. If so, how can I represent that example json as ember model?
Thanks for the help!
For those that are having the same doubt/issue:
http://thejsguy.com/2016/01/29/working-with-nested-data-in-ember-data-models.html
I've created an SPA with multiple ui-views using the state provider.
I have a few url match cases, however I want to make them match not just on an explicit url, example:
app.config(function($stateProvider, paths) {
var base = paths.static.views + 'modules/';
$stateProvider
.state('home', {
url : '/',
views : {
'home' : {
templateUrl : base + 'home/_layout.html',
controller: function() {
console.log('home');
}
}
}
})
.state('foo', {
url : '/foo',
views : {
'foo' : {
templateUrl : base + 'foo/_layout.html',
controller: function() {
console.log('foo');
}
}
},
})
.state('bar', {
url : '/bar*',
views : {
'bar' : {
templateUrl : base + 'bar/_layout.html',
controller: function() {
console.log('bar');
}
}
},
})
.state('dog', {
url : '/dog*',
views : {
'dog' : {
templateUrl : base + 'dog/_layout.html',
controller: function() {
console.log('dog');
}
}
},
});
});
So if I navigate to /foo it works, however if my server has a re-write rule (which it does in some cases) it will re-write it to /foo/ and the match case no longer fires.
I've tried adding {url : '/foo*'} but that didn't work either.
I would really like to fix this!
I have a CouchDB based backend. As in every document-based store, deeply nested properties are first-class citizens. That means, a nested property does not necessarily refer to an independent object. Often, a nested property is just used to structure complex objects, without implying any belongsTo or hasMany relationship. One direct consequence of this is that nested "objects" (which are not really objects) have no IDs.
Since ember-data does not directly supported nested properties, until now I have been modelling these objects using belongsTo relationships, with success. This is the data structure that I am receiving from my backend:
{
"agents": [
{
"_id": "04ef35dd-6ab9-492f-ada6-0d4f4de9610a",
"genproperties": {
"playable-url": null
},
"org_id": 11653,
"outputs": {
"exten": null,
"extension": "c4facb9d-850c-4b67-9592-b467129fa9d4",
"jumpIfBusy": null,
"jumpIfNoAnswer": null,
"nextnode": "a1e00fb9-8604-4119-8515-3a31a36c60d1",
"startnode": null
},
"properties": {
"agent_status": "online",
"allowed_portlets": [
"xxx-portlet",
"yyy-portlet",
"zzz-portlet",
"uuu-portlet",
"ppp-portlet"
],
"default_portlet": "xxx-portlet",
"email": "a.b#c.com",
"enabled_portlets": [
"xxx-portlet",
"yyy-portlet",
"zzz-portlet",
"uuu-portlet",
],
"first_name": "John",
"main-service": null,
"name": "John Ferdinand Smith",
"portlet_language": "en",
"pov-org": null,
"services": {
"associated": {}
},
"surname1": "Ferdinand",
"surname2": "Smith"
},
"type": "wav-user"
},
...
]
}
This is my adapter:
App.Adapter = DS.RESTAdapter.extend({
bulkCommit: false,
namespace: App.config.API_NAMESPACE,
url: mynamespace.apiUrl,
serializer: App.MetaRESTSerializer.create(),
ajax: function(url, type, hash) {
var ajaxPromise = this._super(url, type, hash);
if (App.config.DEBUG_ADAPTER) { console.log('>>>>> REQUESTED > %s:%s > hash=%o ajaxPromise=%o', type, url, hash, ajaxPromise); }
ajaxPromise.then(function(json){
if (App.config.DEBUG_ADAPTER) { console.log('>>>>> RECEIVED > %s:%s > %o', type, url, json); }
});
return ajaxPromise;
}
});
These are my current model definitions:
App.NodeOutputs = DS.Model.extend({
startnode : DS.attr('string'),
jumpIfBusy : DS.attr('string'),
jumpIfNoAnswer : DS.attr('string'),
nextnode : DS.attr('string'),
extension : DS.attr('string'),
exten : DS.attr('string'),
});
App.NodeMixin = Ember.Mixin.create({
nodeType : DS.attr('string'),
nodeSubtype : DS.attr('string'),
outputs : DS.belongsTo('App.NodeOutputs'),
});
App.Adapter.map('App.GenProperties', {
playableUrl : {key: 'playable-url'},
});
App.AgentProperties = App.CommonProperties.extend({
default_portlet : DS.attr('string'),
allowed_portlets : DS.attr('rawTransform'),
portlet_language : DS.attr('string'),
verified_emails : DS.attr('rawTransform'),
email : DS.attr('string'),
agent_status : DS.attr('string'),
});
App.Agent = DS.Model.extend(App.NodeMixin, {
properties : DS.belongsTo('App.AgentProperties'),
genproperties : DS.belongsTo('App.GenProperties'),
});
And these are my mappings:
App.Adapter.map('App.NodeOutputs', {
startnode : {key: 'startnode'},
jumpIfBusy : {key: 'jumpIfBusy'},
jumpIfNoAnswer : {key: 'jumpIfNoAnswer'},
nextnode : {key: 'nextnode'},
extension : {key: 'extension'},
exten : {key: 'exten'},
});
App.Adapter.map('App.Agent', {
nodeType : { key: 'type' },
nodeSubtype : { key: 'subtype' },
outputs : { embedded: 'always' },
properties : { embedded: 'always' }
genproperties : { embedded: 'always' }
});
That was working perfectly with ember-data#0.0.14. Now I am moving to ember-data#1.0.0-beta.3, and it seems the DS.RESTAdapter.map is no longer supported.
I have taken a look at these resources:
the migration guide
and the documentation (hidden on the methods tab)
also a related question
But I still have no idea how to accomplish these two simple tasks:
how to define simple key mappings, like type -> nodeType (json -> ember model)
how to specify that a belongsTo is embedded: 'always'
Question : Is there some sample code showcasing key mappings and embedded properties for the latest ember-data? Does it support embedded properties without IDs?
I have over 30 mappings to migrate, so I'd better make sure to understand what I am doing before starting with it.
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?