How to refresh a model after a request to API - ember.js

//Route
url: "https://xxxxxx.com/api/entries",
users: "https://xxxxxx.com/api/users/",
model: function(){
var localData = JSON.parse(localStorage.getItem("user"));
var data = { auth_token: localData.user_token };
return new Ember.RSVP.hash({
logs: Ember.$.ajax({ url: this.get('url'), headers: { "X-Api-Token": data.auth_token } }),
team: Ember.$.ajax({ url: this.get('users'), headers: { "X-Api-Token": data.auth_token } })
});
}
//controller
actions:{
deleteWorklog: function( worklogId ){
var model = this.get('model.logs');
var data = { auth_token: this.get('local_data').user_token };
Ember.$.ajax({
method: "DELETE",
url: this.get('url') + "/" + worklogId,
headers: { 'X-Api-Token': data.auth_token }
}).then(function(data){
//how do i do it?
})
},
loadMore: function(){
var model = this.get('model.logs');
var url = this.get('url');
var today = new Date();
today.setDate(today.getDate() - this.get('from'));
console.log(today);
url += "?from="+ today.toISOString();
Ember.$.ajax({
url: url,
headers: { "X-Api-Token": data.auth_token }
}).then(function(data) {
model.replace(0, model.length, data);
});
var initial = this.get('from') + 10;
this.set('from', initial);
}
}
}
I'm blocked after the request, i need to refresh my model but i've to do cmd + R to see the change, is there a method re-call the model or something like that?
I've added another things maybe help

There's two ways that I can think of. The first is just to call the refresh method on the route. This is by far the simplest. Just call it and Ember will re-call the model hook for that route and any child routes. In your case, I would send an action from your controller to your route, then have your route refresh itself in that action handler.
The second way would be to manually re-get your data and set it on the controller. Perhaps something like this:
// route.js
actions: {
refreshModel: function() {
var route = this;
Ember.$.ajax({ ... }).then(function(data) {
route.get('controller').set('model', data);
});
}
}
However, I wouldn't recommend this method over the first. There are too many variables when dealing with Ember routing and it's easier just to let Ember handle it all.

You either want to use model.reload to refresh the record from the server:
http://emberjs.com/api/data/classes/DS.Model.html#method_reload
Or you may want to delete the record local:
http://emberjs.com/api/data/classes/DS.Model.html#method_deleteRecord
Or you may want to use model.destroyRecord to let Ember do the delete request (remote + local):
http://emberjs.com/api/data/classes/DS.Model.html#method_destroyRecord
I think it would be the best to use model.destroyRecord, but I assume there's a reason you do this manually?

Related

Ember-data: Empty payload with .save()

Im stuck trying to.save() a record using Ember-Data 1.3 😵
When I perform a .save() nothing goes wrong but the request payload is empty:
I'm pretty convinced it's an issue with the ember-data request because from the back-end side the only data I got it's "token=blahblahblah". Also I took the request (copy as cURL) and I confirm it's empty:
Here's the .save() code:
var self = this;
this.set('isLoading',true);
return this.store.find('feed', feed_id).then(function(feed) {
//Setting the system_status of the feed to either 4 (archived) or 1 (normal)
feed.set('system_status',param);
//Persist to change to store (and server)
console.log(feed);
feed.save().then(function(){
//success
self.set('isLoading',false);
alert('ok');
},function(){
//Error
self.set('isLoading',false);
alert('error');
}) // => PUT to /feeds/id
});
RESTAdapter:
export default DS.RESTAdapter.extend({
host: 'http://localhost:8000/',
namespace: 'ed',
headers: {
"Content-type": "x-www-form-urlencoded" // workaround for laravel
}});
Model console.log before .save()
Any ideas?
The solution is indeed the Serializer, you can change it to send a POST request instead of a PUT request.
Update the DS.RESTAdapter with this code:
updateRecord: function(store, type, snapshot) {
var data = this.serialize(snapshot, { includeId: true });
var id = snapshot.id;
console.log(snapshot);
var url = ENV.apiUrl + "ed/" + snapshot.typeKey + "/" + snapshot.id;
return new Ember.RSVP.Promise(function(resolve, reject) {
jQuery.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: data
}).then(function(data) {
Ember.run(null, resolve, data);
}, function(jqXHR) {
jqXHR.then = null; // tame jQuery's ill mannered promises
Ember.run(null, reject, jqXHR);
});
});

Delete All Record and Create new Records in Emberjs

In my Controller i have open action.this action should remove all record of model and then send ajax request and get new models and replace model. my ember data adapter is LSA
OlapApp.OpenController = Ember.Controller.extend({
needs: ['application'],
actions: {
open: function() {
var self = this;
var xhr = $.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'http://localhost:9095/service.asmx/getModel',
data: '{}',
success: function(response) {
//Success Empty AxisModel;
var data = JSON.parse(response.d);
self.store.findAll('axisModel').then(function(items) {
console.log('try to delete');
items.forEach(function(item) {
item.deleteRecord();
item.save();
});
});
setTimeout(function() {
//Fill Axis Model
_.each(data.axisModel, function(v, i) {
var record = self.store.createRecord('axisModel', {
id: v["id"],
uniqueName: v["uniqueName"],
name: v["name"],
hierarchyUniqueName: v.hierarchyUniqueName,
type: v["type"],
isMeasure: v.isMeasure,
orderId: v.orderId,
isActive: v.isActive,
isAll: v.isAll,
sort: v.sort
});
record.save();
});
self.get('controllers.application').send('showNotification', 'Open', 'success');
}, 2000);
}
});
}
}
});
but when i try to create a new models i get this error :
Assertion failed: The id a12 has already been used with another record of type OlapApp.AxisModel.
Assertion failed: The id a13 has already been used with another record of type OlapApp.AxisModel.
SOLUTION
finally i find the solution.for fix this problem just wrap deleteRecord() in Ember.run.once like this :
self.store.findAll('axisModel').then(function(items) {
items.forEach(function(item){
Ember.run.once(function(){
item.deleteRecord();
item.save();
});
});
});
For deleting records there are problems using forEach because the result of a find to the store is a live array. You can see this discussion in GitHub https://github.com/emberjs/data/issues/772. You can make use of toArray() in order to make a static copy of the live array)
self.store.findAll('axisModel').then(
function(items) {
items.toArray().forEach(function(item){
item.deleteRecord();
item.save();
});
});

Issue with Ember Model promises

I'm trying to do some basic stuff with Ember Model but I'm experiencing some weird behaviors with promises. Not sure I understand very well how it's supposed to work.
So, I have this route:
App.ProfilesIndexRoute = Ember.Route.extend {
redirect: ->
App.Profile.fetch().then (profiles) ->
console.log profiles.get('length')
#transitionTo 'profile', profiles.get('firstObject')
}
I simply want people to be redirected to /profiles/123 (= the first profile) when they access /profiles.
Here is the Profile adapter:
App.Profile.adapter = Ember.Adapter.create {
findAll: (klass, records) ->
$.ajax('/api/users/' + $.cookie('user_id'), {
type: 'get'
headers: {
'Content-Type': 'application/json'
'Authentication-Token': $.cookie('token')
}
dataType: 'json'
}).then (res) ->
profiles = []
// some stuff done here
records.load klass, profiles
}
When I go to /profiles, here is what I see in my console:
0
Transitioned into 'profiles.index'
XHR finished loading: "http://localhost/api/users/456".
0 is the result of console.log profiles.get('length'). It seems that it's called before the AJAX call had the chance to finish. What I should have in my console is something like this:
Transitioned into 'profiles.index'
XHR finished loading: "http://localhost/api/users/456".
5
What am I doing wrong here? Someone here suggested me to use fetch instead of find but it doesn't seem to solve my problem because things are not executed in the right order.
Thank you!
You should redirect to a different route from the afterModel hook:
App.ProfilesIndexRoute = Ember.Route.extend {
model: ->
App.Profile.fetch()
afterModel: (profiles, transition) =>
#transitionTo 'profile', profiles.get('firstObject')
}
Furthermore since you are using # you should use the fat arrow => to have the correct reference to this.
Hope it helps.
I think that the way you are overring the adapter is wrong:
You are using the jquery ajax deferred. But I think that you need to wrap that call in RSVP. Because ember use the RSVP to handle promisses.
Give a look in that implementation
App.Profile.adapter = Ember.Adapter.create({
ajaxSettings: function(url, method) {
return {
headers: {
'Content-Type': 'application/json'
'Authentication-Token': $.cookie('token')
},
dataType: "json"
};
},
findAll: function(klass, records) {
var url = '/api/users/' + $.cookie('user_id'),
self = this;
return this.ajax(url).then(function(data) {
self.didFindAll(klass, records, data);
return records;
});
}
});
I used the findAll implementation from RESTAdapter and just changed the url, to match what you want.
But if your response return just one object, I think that find method is better:
...
find: function(record, id) {
var url = '/api/users/' + $.cookie('user_id'),
self = this;
return this.ajax(url).then(function(data) {
self.didFind(record, id, data);
return record;
});
},
...
I finally found how to solve the problem thanks to this jsFiddle by Erik Bryn.
I was missing a return here:
App.Profile.adapter = Ember.Adapter.create {
findAll: (klass, records) ->
$.ajax('/api/users/' + $.cookie('user_id'), {
type: 'get'
headers: {
'Content-Type': 'application/json'
'Authentication-Token': $.cookie('token')
}
dataType: 'json'
}).then (res) ->
profiles = []
// some stuff done here
records.load klass, profiles
return records // HERE
}
Also, I now use the init method in my ProfilesIndexRoute instead of redirect:
App.ProfilesIndexRoute = Ember.Route.extend {
init: ->
App.Profile.fetch().then (profiles) =>
#transitionTo 'profile', profiles.get('firstObject')
}

Load model like a refresh without ember-data

I'm writing a little ember app without using Ember-Data (using TheMovieDB API) and I don't understand why model is not load when I click on a {{#linkTo}} link, but when I refresh the page manually datas are loaded correctly.
Here is my App.js :
window.App = Ember.Application.create();
App.Router.map(function() {
this.route('about');
this.resource('movie', {
path: '/movie/:movie_id'
})
});
App.IndexRoute = Ember.Route.extend({
setupController: function (controller) {
var movies = [];
$.ajax({
url: "http://api.themoviedb.org/3/movie/popular?api_key=5b088f4b0e39fa8bc5c9d015d9706547",
type: "GET",
async: false,
success: function (data) {
var length = data.results.length;
data.results.forEach(function (item) {
if (item.backdrop_path != null) {
var tmp = item.backdrop_path;
item.backdrop_path = "http://cf2.imgobject.com/t/p/w500/"+tmp+"?api_key=5b088f4b0e39fa8bc5c9d015d9706547"
movies.push(item);
}
})
}
});
controller.set('content', movies);
}
});
App.MovieRoute = Ember.Route.extend({
model: function (param) {
var infos;
/* Important !! */
var promise = Ember.Deferred.create();
$.ajax({
url: "http://api.themoviedb.org/3/movie/"+param.movie_id+"?api_key=5b088f4b0e39fa8bc5c9d015d9706547",
type: "GET",
success: function (data) {
var tmp = data.backdrop_path;
data.backdrop_path = "http://cf2.imgobject.com/t/p/w500/"+tmp+"?api_key=5b088f4b0e39fa8bc5c9d015d9706547";
// infos = Ember.Object.create(data)
promise.resolve(data);
}
});
console.log("MODEL");
return promise;
},
setupController: function (controller, model) {
controller.set('content', model);
}
});
App.Movie = Ember.Object.extend({})
Thanks for your help !
Since you have not specified which model you mean, I'm assuming you mean the movie model, and with my assumption I'm trying to answer.
I think your problem is that your template expects the model coming from a MovieIndexController because you specified a resource in your router map instead of a simple route.
That said, the solution might be to rename your controller to MovieIndexController and respectively the route MovieIndexRoute.
Here the reference my answer is based on, under the paragraph Resources.
Hope it helps

ember-data customs serializing

Hello I am fairly new with ember and exploring it, I have been able to do a simple post to a resource, nevertheless it render my object like this
{"person":{"atribute1":"jjj","atribute2":"jjj"}}
Is there a way to remove the "login" like a custom serializer, my endpoint work by passing an object in the form of
{"atribute1":"jjj","atribute2":"jjj"}
Thanks.
The only solution I could find is override the createRecord, before I had
data[root] = this.serialize(record, { includeId: true });
I removed the index of root and got this instead:
App.Store = DS.Store.extend({
revision: 11,
adapter : 'App.CustomAdapter'
});
App.CustomAdapter = DS.RESTAdapter.extend({
createRecord: function(store, type, record) {
var root = this.rootForType(type);
var data = {};
data = this.serialize(record, { includeId: true });
this.ajax(this.buildURL(root), "POST", {
data: data,
context: this,
success: function(json) {
Ember.run(this, function(){
if ( this.rootForType(type) == 'login' ) {
return;
}
this.didCreateRecord(store, type, record, json);
});
},
error: function(xhr) {
//HERE to handle login operation failed
this.didError(store, type, record, xhr);
}
});
}
});
Maybe a attribute like withRoot or something similar might be required.