How can I fetch a single model from the server using Ember Data?
For example, I have url for my server api localhost:8080/rest/setting, and respond is JSON object
{
"siteName": "lala",
"siteUrl": "blabla"
}
In the result I want to use this model for rendering in my template.
I'm going to assume you meant to say "...can I fetch a single model from the server without using Ember Data", in which case of course you can! Just use jQuery to get your data. For example:
App.ExampleRoute = Em.Route.extend({
model: function (params) {
return Ember.$.ajax({
type: "GET",
url: 'localhost:8080/rest/setting',
dataType: 'json'
});
}
App.Setting = DS.Model.extend({
sitename: DS.attr()
});
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://localhost:8080', // this isn't necessary, since it'll use the current server's host
namespace: 'rest' // this is appended to your current web server host http://server/rest
});
App.Router.map(function() {
this.resource('foo', {path:'/:foo_id'});
});
App.FooRoute = Em.Route.extend({
model: function(params){
// if param.foo_id is 1 then
// this would be http://localhost:8080/rest/setting/1
return this.get('store').find('setting', params.foo_id);
}
});
your JSON should come back in this format:
{ setting: { "siteName": "lala", "siteUrl": "blabla" } }
If you want it to be in a different format you need to use a serializer and massage the data into the format Ember is expecting: https://github.com/emberjs/data/blob/master/TRANSITION.md
Related
I'm trying to use ember-data with jsonp by overridding DS.RESTAdapter's findAll (based on the answer to this question).
App.ApplicationStore = DS.Store.extend({});
App.Event = DS.Model.extend({
name: DS.attr('string')
});
App.EventAdapter = DS.RESTAdapter.extend({
findAll: function() {
var events = [];
$.ajax({
url: '...',
dataType: 'jsonp',
success: function(response) {
response.results.forEach(function(event) {
events.addObject(App.ApplicationStore.createRecord('event', event));
}, this);
}
});
return events;
}
});
App.EventsRoute = Ember.Route.extend({
model: function() {
return this.store.find('event');
}
});
I first tried using events.addObject(App.Event.create(event)), but ember returned an error: "You should not call create on a model. Instead, call store.createRecord with the attributes you would like to set".
The issue is, App.ApplicationStore.createRecord is undefined, so I'm stuck without a way to instantiate Events. Anyone know what's going on? If there's a completely different approach to getting jsonp to work with ember-data, that's fine too.
This parsing of the response seems more like a job for the RESTSerializer than the RESTAdapter(though you will still need the adapter if you need to set the dataType/url)
Not 100% sure, but it looks like your reponse is an array that doesn't have the correct key
as stated in the jsonapi.org documenation?
If this is the case, you'd want to create a serializer for events like this
App.EventsSerializer = DS.RESTSerializer.extend({
extractFindAll: function(store, type, rawPayload, id, requestType) {
this._super(store, type, { 'events': rawPayload }, id, requestType);
}
});
The above serializer will reformat the response to be ember-data readable(as per the above documentation), and ember-data will take care of the rest
DS.RESTSerializer documentation
As an aside, the current store is passed as the first parameter to DS.RESTAdapter.findAll, so you should access the store through that parameter
<\EDIT>
including DS.RESTAdapter.findall source
kaungst's answer was really helpful, but ember was still throwing an error. It led me to a solution that works, though:
App.EventSerializer = DS.RESTSerializer.extend({
normalizePayload: function(payload) {
return {'events': payload};
}
});
App.EventAdapter = DS.RESTAdapter.extend({
findAll: function(store) {
var events = [];
$.ajax({
url: '...',
dataType: 'jsonp',
success: function(response) {
response.results.forEach(function(event) {
events.addObject(store.createRecord('event', event));
}, this);
}
});
return events;
}
});
I overrode DS.RESTSerializer's normalizePayload instead of extractFindAll, which fixed the subsequent error I was getting. Additionally, I defined App.EventSerializer (singular) instead of App.EventsSerializer.
I'm using Ember Model and I would like to set up a URL prefix for all my models, instead of prepending them on each model like this:
App.MyModel = Ember.Model.extend({
id: attr(),
myAttr: attr()
});
App.MyModel.reopenClass({
url: ajaxUrl + '/some/obscure/path'
});
I'm aware I could probably override Ember.Model so that url defaults to ajaxUrl, but then if I want to set it to something other than default, like in the example above, I would have to prepend it.
If this is not possible, is there a recommended way to set a default url?
The best solution I came up with is to extend Ember.RESTAdapter itself.
Ember.RESTAdapter = Ember.RESTAdapter.extend({
ajaxSettings: function(url, method) {
return {
url: ajaxUrl + url,
type: method
};
}
});
App.MyModel = Ember.Model.extend({
id: attr(),
myAttr: attr()
});
App.MyModel.reopenClass({
adapter: Ember.RESTAdapter.create(),
url: '/some/obscure/path'
});
Because that's the adapter I use for my models. I guess it's not ideal, but it works ok.
I have started a simple example using the fixture Adapter. When I navigate to my route /teams, I can see all Teams i have registered in my adapter.
Now I changed my code to register the Default restadapter:
Football.ApplicationAdapter = DS.RESTAdapter.reopen({
host: "http://localhost:8080/MatchService.svc/json"
});
When I now navigate to my route /Teams, I can see no Errors, the site looks as it should, just without no Teams listed in the list.
Then I started to have a look at the Network-Traffic: No calls are being sent, nothing.
But: When I try to add a team (I havent implemented this Method in rest service yet), I can see that there is a call going to
localhost:8080/MatchService.svc/json...
and offcourse, I get a 404.
But why dont I get a call against
localhost:8080/MatchService.svc/json/teams
when I navigated to my Teams-route?
Here is my route:
Football.TeamsRoute = Ember.Route.extend({
model: function() {
return this.store.all('team');
}
});
I changed it already from this.store.find .... to this.store.all... because after using the restadapter I got an "error while loading the route : undefined".
I also added the current ember.js -Version as reference from the ember site.
Thats the json which gets returned by the Server:
{"TeamsResult":[
{"ID":1,"Name":"Deutschland"},
{"ID":2,"Name":"Frankreich"}
]}
I also tried a a not wrapped json result from the WebService:
{[{"ID":1,"Name":"Deutschland"},{"ID":2,"Name":"Frankreich"}]}
all doesn't make a call to the server, it just returns all of the records already fetched client side. you should use this.store.find('team')
Additionally you should define your adapter using extend:
Football.ApplicationAdapter = DS.RESTAdapter.extend({
host: "http://localhost:8080/MatchService.svc/json"
});
reopen applies it to every instance created of the rest adapter, which may not be appropriate.
Here's a small example that shows the basic structure of your app:
Football = Ember.Application.create();
Football.Router.map(function() {
this.resource('teams', {path:'/teams'});
});
Football.TeamsRoute = Ember.Route.extend({
model: function() {
return this.store.find('team');
}
});
Football.ApplicationAdapter = DS.RESTAdapter.extend({
host: "http://localhost:8080/MatchService.svc/json"
});
Football.Team = DS.Model.extend({
name: DS.attr()
});
For convenience sake I mocked the call to http://localhost:8080/MatchService.svc/json/teams with what Ember Data is expecting as a response:
{
teams:[
{
id: 1,
name: "Miami Heat"
},
{
id: 2,
name: "Seattle Seahawks"
},
{
id: 3,
name: "Texas Longhorns"
}
]
}
http://emberjs.jsbin.com/OxIDiVU/425/edit
I want to retrieve information through a REST request and set up a RESTAdapter like this:
App.ApplicationAdapter = DS.RESTAdapter.extend({
url: 'http://whatever.local'
});
Ember is doing a GET request but is not appending a parameter if I try do to a this.store.find('entry', 11) or this.store.findQuery('entry', {foo:'bar'})
Additionally it does not send the request to the url I defined. It just sends it to the host the app is running on.
Therefore I'm guessing I initialize the Adapter not properly, but cant seem to find the answer what I am doing wrong.
App.OverviewRoute = Ember.Route.extend({
model: function (params) {
console.log(params);
var entries = this.store.findQuery('entry', {periodDate: params.period_id});
return entries;
}
});
Help is appreciated.
Starting in EmberData 1.0.beta.1, the adapter option is host, not url (see here in the transition guide):
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://whatever.local'
});
I am looking for a guide that will help me understand syncing models in ember. I tried to use the RestAdapter on the latest build and I am getting an error. So I decided to use the BasicAdapter based on stabilizing ember data on the ember js site.
Here is my model:
App.Accounts = DS.Model.extend({
name:DS.attr('string')
,date:DS.attr('date')
})
Here is where I declare the sync functions for the model.
App.Accounts.sync = {
list: function() {
$.ajax({
type: 'POST',
cache: false,
url: contextPath + 'account/list',
success: function(data) {
this.load()
},
error: function(jqXHR, textStatus, errorThrown) {
},
async: false
});
}
}
I am calling the list function in a setup controller:
App.TestRoute = Ember.Route.extend({
setupController:function(){
App.Accounts.list()
}
})
The function does not execute. What is the correct way to call sync functions in an ember application? Also, I could use a blog/article on this topic.
Thanks!
Have you checked out Ember Model it gives you a basic adapter without having to use EmberData.
Erik has a tutorial at embercasts.com you may need to signup to be beta user.
var attr = Ember.attr;
App.User = Ember.Model.extend({
id: attr(),
name: attr()
});
App.User.url = "/users";
App.User.adapter = Ember.RESTAdapter.create();
var newUser = App.User.create({name: "Erik"});
newUser.save(); // POST to /users.json
var existingUser = App.User.find(1); // GET /users/1.json
existingUser.set('name', 'Kris');
existingUser.get('isDirty'); // => true
existingUser.save(); // PUT /users/1.json
Cheers