I've recently started learning Ember, and am now trying to understand how to use Ember Data to make an ajax call for data. I would like to get data and log the response to the console when I navigate to the pages'route.
Here is the code I have but cannot get it to log the data:
Handlebars and JS:
<script type="text/x-handlebars">
<nav>
{{#link-to 'home'}}Home{{/link-to}}
{{#link-to 'pages'}}Pages{{/link-to}}
</nav>
<div class="container">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="pages">
Info here
{{log}}
</script>
App = Ember.Application.create();
App.Router.map(function() {
this.route('home', {path: '/'});
this.route('home', {path: 'home'});
this.route('pages', {path: 'pages'});
});
App.Pages = DS.Model.extend({
status: DS.attr('string'),
startDate: DS.attr('string'),
lastModifiedDate: DS.attr('string'),
author: DS.attr('string'),
lastModifiedBy: DS.attr('string'),
title: DS.attr('string'),
items: {}
});
App.PagesAdapter = App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'https://api.mongolab.com/api/1/databases/emberdatatest/collections/itemdata?apiKey=somekey'
});
App.PagesRoute = Ember.Route.extend({
model: function() {
this.store.find('pages');
}
});
Here is the data I cam getting back as a response:
{
"_id": {
"$oid": "5460cc6be4b0933065794003"
},
"start": 0,
"count": 5,
"total": 1549,
"pages": [
{
"status": "published",
"startDate": "2014-09-24 12:56",
"lastModifiedDate": "2014-10-02 12:01",
"author": "Luke Skywalker",
"lastModifiedBy": "Darth Vader",
"title": "home page",
"items": {}
},
{
"status": "published",
"startDate": "2014-10-13 08:03",
"lastModifiedDate": "2014-10-02 12:01",
"author": "Sauran",
"lastModifiedBy": "Gandolf",
"title": "Blog page",
"items": {}
},
{
"status": "review",
"startDate": "2014-11-22 13:03",
"lastModifiedDate": "2014-11-14 14:01",
"author": "Jean-Luc Piccard",
"lastModifiedBy": "Worf",
"title": "Vacuum Cleaners page",
"items": {}
}
]
}
Instead of
this.store.find('pages');
you should call
this.store.find('page');
it's going to make request to
https://api.mongolab.com/api/1/databases/emberdatatest/collections/itemdata?apiKey=somekey/pages
Then the api should give you back response in following format (in case of using Rest adapter)
"posts": [{
"id": 1,
"status": "foo",
"startDate": "foo",
"lastModifiedDate": "foo",
"author": "foo",
"lastModifiedBy": "foo",
"title": "foo"
}]
Inside your router model method you should return the results from anonymous function
App.PagesRoute = Ember.Route.extend({
model: function() {
return this.store.find('pages');
}
});
Then you can check in ember inspector whether everything was all right.
If you can't force your api to return expected format you can do it without ember data
App.PagesRoute = Ember.Route.extend({
model: function() {
return jQuery.getJSON('https://api.mongolab.com/api/1/databases/emberdatatest/collections/itemdata?apiKey=somekey/', function(json) {
return json
});
}
});
If you want to use ember data I advise you to look here:
http://emberjs.com/guides/models/finding-records/
http://emberjs.com/guides/models/connecting-to-an-http-server/
http://andycrum.github.io/ember-data-model-maker/
Related
I tried a simple emberapp to display some userdata.
My API returns me this json:
{
"roles":[
{
"id":5,
"name":"admin",
"alias":"Administrator",
"users":[
{
"id":1,
"username":"Evolutio",
"email":"mail#evolutio.tld",
"display_role":"Administrator"
}
]
},
{
"id":2,
"name":"user",
"alias":"Benutzer",
"users":[
]
},
{
"id":1,
"name":"banned",
"alias":"Gesperrt",
"users":[
]
},
{
"id":3,
"name":"mod",
"alias":"Moderator",
"users":[
]
},
{
"id":4,
"name":"support",
"alias":"Supporter",
"users":[
]
}
]
}
my user/model.js:
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr('string'),
email: DS.attr('string'),
display_role: DS.attr('string'),
roles: DS.belongsTo('role'),
});
and my role/model.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
alias: DS.attr('string'),
users: DS.hasMany('user'),
});
With this setup I got this error in my developer console:
Error while processing route: team.index Assertion Failed: Passing classes to store methods has been removed. Please pass a dasherized string instead of undefined EmberError#
I didn't get the mistake. Maybe anyone can help me for this.
You would need to sideload the data and make your API return data like this:
{
"users": [{
"id": 1,
"username": "Evolutio",
"email": "mail#evolutio.tld",
"display_role": "Administrator",
"roles": [5]
}],
"roles": [{
"id": 5,
"name": "admin",
"alias": "Administrator",
"users": [1]
}, {
"id": 2,
"name": "user",
"alias": "Benutzer",
"users": []
}, {
"id": 1,
"name": "banned",
"alias": "Gesperrt",
"users": []
}, {
"id": 3,
"name": "mod",
"alias": "Moderator",
"users": []
}, {
"id": 4,
"name": "support",
"alias": "Supporter",
"users": []
}]
}
If you must embed the data like you did, you might want to look into EmbeddedRecordsMixin[http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html]
But I would like to suggest few things:
1) follow json-api(http://jsonapi.org/) since ember data follows it and supports it out of the box( starting from ver 1.13.0 I think)
2) Take it or throw it idea - I don't know your requirement but ideally user model would have hasMany relationship to roles. So I would do things bit differently like this:
//user/model.js:
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr('string'),
email: DS.attr('string'),
//display_role: DS.attr('string'),//you don't need this, since user can have multiple roles and also you can access it from the user model itself by doing model.roles.forEach((role)=>{ role.alias or role.name})
roles: DS.belongsTo('role')
});
//role/model.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
alias: DS.attr('string')
});
because generally there will be fewer roles than users and also you wouldn't want to load all that data(roles and users) in one request call.
Ember Data 2.1.0 ignores the links property in my JSON response and fires the following request instead:
/point_logs/3e5ff053422f40e3a8057fc5e8100c47
Also for each point log found it fires a single request. Instead I want it to fetch a collection of all point logs.
In Ember 1.x everything worked fine though. Looked everywhere for an answer but unfortunately I was unable to find a solution so far.
Appliance Model
var DirectObject = DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
type: DS.attr('string'),
createdDate: DS.attr('date'),
modifiedDate: DS.attr('date'),
deletedDate: DS.attr('date'),
pointLog: DS.belongsTo('pointLog')
});
Pointlog Model
var PointLog = DS.Model.extend({
unit: DS.attr('string'),
type: DS.attr('string'),
lastConsecutiveLogDate: DS.attr('date'),
updatedDate: DS.attr('date'),
directObject: DS.belongsTo('directObject')
});
JSON Response
{
"data": [
{
"id": "6dbcf32a3e064a36a1db4847329cc90d",
"type": "appliance",
"attributes": {
"name": "3974737",
"description": "",
"type": "zz_misc",
"createdDate": "2015-09-15T14:23:02.768Z",
"modifiedDate": "2015-10-08T08:39:15.525Z",
"deletedDate": null
},
"relationships": {
"pointLog": {
"data": {
"id": "3e5ff053422f40e3a8057fc5e8100c47",
"type": "pointLog"
},
"links": {
"related": "/core/appliances/6dbcf32a3e064a36a1db4847329cc90d/point_log"
}
}
}
}
],
"included": [],
"links": {
"self": "/core/appliances"
}
}
I've also tried using the self property instead of related. And also related as an object with an href property inside being the url.
Ok so I figured it out. The problem is the data property. It seems that if it is present, Ember will make individual calls without using the url given in the links object.
Before
"relationships": {
"pointLog": {
"data": {
"id": "3e5ff053422f40e3a8057fc5e8100c47",
"type": "pointLog"
},
"links": {
"related": "/core/appliances/6dbcf32a3e064a36a1db4847329cc90d/point_log"
}
}
}
After
"relationships": {
"pointLog": {
"links": {
"related": "/core/appliances/6dbcf32a3e064a36a1db4847329cc90d/point_log"
}
}
}
I am a newbie to NodeJS and Sails.js.
I want create a REST API that allows me to expand a resource based on query parameter. For eg
HTTP GET /snippets
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "http://localhost:8000/snippets/1/",
"highlight": "htep://localhost:8000/snippets/1/highlight/",
"title": "test",
"code": "def test():\r\n pass",
"linenos": false,
"language": "Clipper",
"style": "autumn",
"owner": "http://localhost:8000/users/2/",
"extra": "http://localhost:8000/snippetextras/1/"
}
]}
HTTP GET /snippets?expand=owner
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "http://localhost:8000/snippets/1/",
"highlight": "http://localhost:8000/snippets/1/highlight/",
"title": "test",
"code": "def test():\r\n pass",
"linenos": false,
"language": "Clipper",
"style": "autumn",
"owner": {
"url": "http://localhost:8000/users/2/",
"username": "test",
"email": "test#test.com"
},
"extra": "http://localhost:8000/snippetextras/1/"
}
]}
Wondering how can I do that in Sails.js or NodeJS?
You should use assocations.
Here is how you would create a one-to-many association between your User model and your Snippet model:
// User.js
module.exports = {
// ...
attributes: {
// ...
snippets: {
collection: 'Snippet',
via: 'owner'
}
}
};
// Snippet.js
module.exports = {
// ...
attributes: {
// ...
owner: {
model: 'User'
}
}
};
Then you can hit /snippets if you want a list of snippets, and hit /snippets?populate=[owner] if you need details about the owners of the snippets.
I have this error when try call rest api : Encountered "companies" in payload, but no model was found for model name "company"
http://localhost:9000/api/insurance/travel/companies
Call example :
var companies = this.store.find("insurance/travel/company");
Model :
export default DS.Model.extend({
name: DS.attr('string'),
url: DS.attr('string'),
logoUrl: DS.attr('string'),
contactUrl: DS.attr('string'),
moreUrl: DS.attr('string'),
about: DS.attr('string')
})
JSON Example :
{
"companies": [
{
"id": "id1",
"name": "test",
"url": "http://google.com",
"logoUrl": "http://google.com",
"contactUrl": "http://google.com",
"moreUrl": "http://google.com",
"about": "about text"
},
{
"id": "id2",
"name": "test 2",
"url": "http://google.com",
"logoUrl": "http://google.com",
"contactUrl": "http://google.com",
"moreUrl": "http://google.com",
"about": "about text"
}
]
}
Create an adapter and inject a inflector
import DS from 'ember-data';
import Ember from 'ember';
var inflector = Ember.Inflector.inflector;
inflector.uncountable('company');
export default DS.RESTAdapter.extend({});
It worked for me
I'm using ember rc3 and ember-data 12 (sha e324f0e) (basically the files recommended in the guides). I have 2 models set up as follows:
App.User = DS.Model.extend({
username: DS.attr('string'),
playerType: DS.attr('string'),
cars: DS.hasMany('App.Car')
})
App.Car = DS.Model.extend({
name: DS.attr('string'),
thumb: DS.attr('string'),
user: DS.belongsTo('App.User')
})
The json returned is
{
"cars": [
{
"id": "50ace47234fa7557403e7f02",
"name": "Dodge Charger SRT8",
"thumb": "/static/images/carthumbs/18331.png",
"user_id": "502a754b34fa75280c000a7e"
},
{
"id": "508668cc34fa753b78784ca2",
"name": "BMW M3 Coup\u00e9",
"thumb": "/static/images/carthumbs/23250.png",
"user_id": "502a754b34fa75280c000a7e"
},
{
"id": "50c7545334fa750ab8cb3ac2",
"name": "BMW Z4 M Coup\u00e9",
"thumb": "/static/images/carthumbs/7618.png",
"user_id": "502a754b34fa75280c000a7e"
},
{
"id": "50adf64c34fa750bb036121e",
"name": "2013 Ford Shelby GT500\u2122",
"thumb": "/static/images/carthumbs/24824.png",
"user_id": "502a754b34fa75280c000a7e"
}
],
"user": {
"id": "502a754b34fa75280c000a7e",
"car_ids": [
"50ace47234fa7557403e7f02",
"508668cc34fa753b78784ca2",
"50c7545334fa750ab8cb3ac2",
"50adf64c34fa750bb036121e"
],
"player_type": "Standard Player",
"username": "WillMckenzie"
}
}
Everything seems to load fine if I call App.User.find("502a754b34fa75280c000a7e"), but when I try and access the cars property on the user it triggers a second http request to the cars api route. It was my understanding that this shouldn't be necessary, and if I change the ids to basic ints, it doesn't. As I'm using Mongo as my DB my ids have to be in this string format.
Any suggestions as to what I'm doing wrong?
Cheers
Will
Here's the answer so people don't have to dig through the comments:
"I had one car id listed that wasn't in the list of cars returned. They're grabbed slightly differently and I obviously had a bad record in there. This meant it always thought it needed to reload that record so would keep requesting. Obviously when I was faking the integer ids it was masking this." - OiNutter