Reputation: 1376
I have something like:
App.IndexController = Ember.ObjectController.extend({
results : function(){
return new Ember.RSVP.Promise(function(resolve, reject){
Ember.$.getJSON('/search').then(function(res){
console.log('response data is: ', res);
resolve(res)
})
})
}.property(),
...
})
// data
$.mockjax({
url: '/search',
responseText : {
type: 'different people',
res: [
{name: 'charlie', age: '55'},
{name: 'bobby', age: '19'},
{name: 'raymond', age: '39'}
]
}
})
How do I actually use the returned data? Currently, results
returns a promise ( this.get('results')
) so I can't use it in my hbs template. Do I need to convert it to an object and then return that object?
Upvotes: 0
Views: 583
Reputation: 1555
Internally Ember uses a PromiseProxyMixin to do the magic rendering of promises that we know and love. Here is your updated JSBin working with a PromiseProxy:
http://emberjs.jsbin.com/danazu/edit?html,js,output
Your results
property becomes this:
results: Ember.computed.promise(function(resolve, reject) {
Ember.$.getJSON('/search').then(function(res) {
console.log('response data is: ', res);
return resolve(res);
});
})
However I don't recommend this. Take a look at this discourse thread to get some information on why you might not want to do this. In short, it will be clunky to handle all the different states of promises.
The Router is the perfect place to deal with promises with AJAX requests. There must be some reason that you're not just loading this data in your Router in the model
or afterModel
hooks. Could you create another nested resource to represent these search results and then just link-to
that resource?
In your Router:
Router.map(function() {
this.resource('search', { path: '/search/:term' });
});
App.PeopleRoute = Ember.Route.extend({
model: function(params) {
return Ember.$.getJSON('/search?term=' + params.term);
}
});
If that won't work at the very least you could:
action
when you want the search resultsresults
on the controller when they are resolved.Upvotes: 1
Reputation: 8724
I use ic ajax for easy use with promises. I don't currently use Ember data so I wrote myself a nice rest client on top of ic ajax to easily get/post/put to urls:
rsvpAjax: function(url,method, data){
var headers = {};
// build request
var opts = {};
var defaultOpts = {
type: method,
headers: headers,
data: JSON.stringify(data),
dataType: 'json',
xhrFields: {
withCredentials: true
}
};
return ajax.request(url, $.extend({}, defaultOpts, opts));
}
And then I have get method:
getAsync: function(url){
return this.rsvpAjax(url, "GET");
}
Then using it elsewhere in a facade/helper class:
import objFactory from 'appname/models/obj';
...
...
foo: function(){
//get your rest client somehow
var apiFacade = this.getRestClient();
return restClient.getAsync('url_string').then(function(response){
//targets some part of the response - here its an array of
var data = response.data;
return data.map(function(obj){
return objFactory.create(obj);
});
});
}
foo
returns an array of Ember objects. the objFactory
I import is just a Ember.Object class. The obj
passed into the create generally is a one to one match with the properties in said Ember.Object. With an initializer, I inject this object into every route:
import someFacade from "app/facades/facade";
export default {
name: 'someFacade',
initialize: function(container, app) {
//a singleton by default
container.register('facades:someFacade',someFacade);
app.inject('route', 'someFacade', 'facades:someFacade');
}
};
Any of my routes can use this facade without importing it thanks to DI.
//Ember blocks
model: function(){
return this.someFacade.foo();
}
or:
setupController(controller, model){
//set controller prop on return of resolved val
this.someFacade.foo().then(function(foosReslovedVal){
controller.set('someProp', foosResolvedVal);
});
}
Upvotes: 0