I'm new to Ember, and am having a problem I'm not seeing duplicated anywhere else so I'm sure I'm doing something silly. I have these models:
App.User = DS.Model.extend({
username: DS.attr("string"),
userId: DS.attr("number"),
modules: DS.hasMany("App.Module")
});
App.Module = DS.Model.extend({
moduleId: DS.attr("number"),
name: DS.attr("string")
});
Note that my Module model is simply a container that a User can have a few of, and many users might share the same modules - they're actually represented by an Enum on the server. As such, the backend does not have a mapping of Module > Users, so I've left the DS.ownedBy or DS.hasMany out of App.Module. I have, however, tried my test with a "users: DS.hasMany('App.User')" in there as well, with the same result. If it turns out to be necessary, I could maintain such a mapping, but I have no other reason for doing so right now, so it would be a bit unfortunate to be forced to add such a table to my database.
I'm using Ember.Auth for authentication, and when my app loads up and I log in, the server requests (as expected):
users/nathan?authToken=<token>
The result is also as I think it should be, according to the ember data docs:
{
"user": {
"username": "nathan",
"user_id": 1,
"module_ids": [1,2]
},
"modules": [
{"module_id": 1, "name": "Account Settings"},
{"module_id": 2, "name": "Manage Websites"}
]
}
I'm then testing in the Chrome console with:
App.Auth.get("user").get("modules");
or
App.User.find("nathan").get("modules");
and in both cases, Ember makes a request to my server to get the data for Modules 1 and 2. If I repeat the same request, it doesn't go back to the server again, so it is storing the result properly that time, it's simply the sideload that it's ignoring.
I'm using ember-1.0.0-rc4 with ember-data-0.13.
In your sideload response, module_id should be id.
(or you can configure ember-data to use module_id, but formatting the server response should be the easier way?)
--- edit for explanation ---
I'm not sure the original REST call is "working perfectly". Without the id. ember-data does see the two modules that your originally sideloaded, but it sees no id, so it does not know that they are modules 1 and 2 respectively. By default (changeable), ember-data expects the id to be called id; your module_id (and user_id) are just treated as regular properties.
On your next API call (to /modules?ids[]=1&ids[]=2 presumably), ember-data silently assumes that, since your requested two modules, and two modules came back, they should be the two that you requested. Try sending back this
{
"modules": [
{"module_id": 3, "name": "Foo module"},
{"module_id": 4, "name": "Bar module"}
]
}
for the request /modules?ids[]=1&ids[]=2, you will still get your "successful" observation.
Try App.Module.find(1).get('name') with the module_id-response - you will get undefined; now try it with the id-response, and you will get Account settings as expected.
Have you configured your RestAdapter to sideload modules?
Like this:
DS.RESTAdapter.configure('App.Module', {
sideloadsAs: 'modules'
});
Related
I currently have a response like so from my API:
{
"data": [{
"attributes": {
"customer_name": "The Name",
},
"id": 1,
"relationships": {
"tasks": {
"data": [{
"attributes": {
"name": "The task",
},
]
}
},
"type": "customer"
}
]
}
And Ember loads the model correctly. However, when I try and consume the computed property the relationship creates, Ember initiates an OPTIONS and subsequent GET request for each item in the relationship.
I haven't worked with these kinds of relationships before so this may be the expected behaviour but I'm a bit confused.
If it is going to do a request for each one, why bother sending the items as part of the original model via a relationship at all? Why not just do a normal model retrieval which would probably be much quicker.
It seems really wasteful so I suspect I'm not handling or understanding something correctly, I'd appreciate any insight.
This is expected behavior for what you are doing (accessing a hasMany relationship). In your example, the tasks do not exist in Ember Data's store so when trying to access them Ember Data is smart enough to fetch them for you from your API. In doing so, it sends out the OPTIONS and GET requests to retrieve them. The OPTIONS request is simply a preflight request.
If you wanted to work with this particular model and its tasks (or other hasMany relationship models) without making so many network requests, you could fetch both simultaneously by requesting them with an include assuming you're using an adapter that allows it (i.e., supports the JSON API spec) and your API does too:
// for example, fetching a post with its comments (hasMany relationship)
this.store.findRecord('post', params.post_id, { include: 'comments' } );
Doing so should return the model and its tasks in one network request. For further reading, I'd checkout Ember's guide on Relationships.
Am using ember-models-table to display table in my applicaiton. The table is great for sorting , pagination etc, but am trying to route from specific row to different page based on the id. it has mentioned in its example to use 'routeName'
But when I use it throws the following error:
"Assertion Failed: When calling warn you must provide an options hash as the third parameter. options should include an id property."
My .js coding :
columns:[
{
"propertyName": "firstName",
"title":"First Name",
"routeName":"/#/profile/_id"
},
and so on
Thanks for your help.
update: the error is gone after updating ember to ember 3.1.2
but there is a warning and its not functioning properly as expected , where am i going wrong?
my code :
columns:[
{
"propertyName": "firstName",
"title":"First Name",
"routeName":"profile"
},
If you look at the example app for this addon, you'll see the following syntax for the route:
{
propertyName: 'id',
routeName: 'users.user'
},
This roughly corresponds to a route like users/1. So, if this is your router:
Router.map(function() {
this.route('users', function() {
this.route('user', { path: '/users/:user_id' });
});
});
And here are the columns:
columns: [
{
"propertyName": "something",
"routeName": "users.user"
},
{
"propertyName": "id",
"routeName": "users.user"
}
]
Here's the template:
{{models-table
data=model
columns=columns
...
}}
routeName should not include the id segment.
Hover over the anchor tag created to see where it leads to, and make adjustments until it matches where it should go. It will only render when there's a valid route for the link. The path seems like it might be relative, so if you're already on the users route, you may only need to specify user for the routeName.
I figured this out by searching the addon codebase for routeName and then trying it out with the same kind of format that {{link-to}} helper uses in Ember.
P.S. this is some missing info in the documentation, so if this addon is helping you out, consider making a PR to help others.
I've come unstuck when trying to fetch a single record using Ember Data 2.
The server is designed to respond to a GET request like this:
GET http://server/api/results/1
with this as a result:
{
"results" : [
{
"id": 1,
"catname": "Category 1",
}
]
}
The Ember route code looks like this:
export default Ember.Route.extend({
model: function() {
return this.store.find('game',12);
}
});
The problem is that there doesn't appear to be a network request going out (a previous findAll fetch has worked, so I don't think it's the adapter), and there is an error I have not been able to find informaiton on:
Uncaught TypeError: Cannot set property'crossDomain' of undefined
Does anyone have any idea what this could be, of hint at how I might track this down?
In 1.13 new methods was introduced. You should use findRecord instead of find.
Also, ember expects following response when fetching a single object:
{
"result" :
{
"id": 1,
"catname": "Category 1",
}
}
I'm trying to upgrade my Ember application to the latest Ember 1.13.2 and therefore am trying to replace all Ember.ArrayController with Ember.Controller.
I've got a problem with the category-controller of my blog. The data retrieved from my server looks like this:
"posts": [
{
"category": {
"id": "1",
"name": "tech"}
"title": "my title",
"body": "post-content",
"isPublished": true,
},
...
]
In my category-controller I need both, the category-id and the category-name.
With the Ember.ArrayController I used objectAt(0) to get both from the first post loaded in the model for that purpose but this doesn't work with Ember.Controller anymore.
How can I get these two attributes in my controller?
This code doesn't work anymore:
breadCrumb: function(){
return this.objectAt(0).get('category').get('name');
}.property('model.[]'),
categoryId: function(){
return this.objectAt(0).get('category').get('id');
}.property('model.[]'),
You just get it from the model directly instead of using the proxy behavior:
return this.get('model').objectAt(0).get('category').get('name');
Or, if you like shorthand:
return this.get('model.firstObject.category.name');
EDIT: While I'm at it, you could also declare these as aliases:
breadCrumb: Ember.computed.alias('model.firstObject.category.name'),
If you don't do that, you should probably change your dependent key. Your property won't update if the nested properties change. You need to use something like model.firstObject.category.name or model.#each.category.name.
What I'm Trying:
Persist a new record but for some reason the request payload is empty even though the record has data.
Here's a fiddle: http://jsfiddle.net/brancusi/m8VrB/16/
(Disregard the firebase, it's just there so we can inspect the request payload on save.)
Explanation:
You will notice that when you save the record, the request payload is empty.
Ideally the request payload would look something like this:
{
"inventory": {
"entry_time": "2014-02-05",
"client_id": 1,
"user_id": 1,
"product_stock_levels": [
{
"product_id": 1,
"quantity": 2
},
{
"product_id": 2,
"quantity": 0
},
{
"product_id": 3,
"quantity": 8
}
]
}
}
Notes:
This only seems to be a problem when it's a new record. Updating existing records send the correct payload.
You are expecting ember data to embed relationships in a model on save as default. This is not the default behavior.
You could define relationships as being embedded per model. But there is no support for embedded record feature anymore as stated here: https://github.com/emberjs/data/blob/master/TRANSITION.md I am not sure if basic embedded record features still work with latest version of ember data. But you define a record as embedded like this:
App.InventorySerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
productStockLevels: {embedded: 'always'}
}
});
Because core team stopped support for this embedded records feature and it is very basic I would recommend you to use EmbbededAdapter or EmbeddedMixin if you need support for embedded records. You find them here: https://github.com/pixelhandler/ember-data-extensions
But as Ember Data EmbeddedAdapter is not stable yet. Perhaps you should consider not to embedded records to reduce complexity if you are flexible in defining the api.