I'm lost in Ember data promises and hasMore relationships. Here's what I have:
tarifs and reservations are both loaded (with success) at application start:
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return Em.RSVP.hash({
tarifs: this.store.find('tarif'),
reservations: this.store.find('reservation')
});
}
});
Then, tarifs and reservations are bounded to spectacles:
App.SpectaclesRoute = Ember.Route.extend({
isLoaded:false,
model: function() {
if(this.isLoaded) {
return this.store.all('spectacle');
}
this.isLoaded = true;
return this.store.find('spectacle');
}
});
Spectacles are returned by the server with a representations ID array and a tarifs ID array. Representations objects are returned in the same response, below. Tarifs are already in the store, thanks to the first call.
Here's the Spectacle model:
App.Spectacle = DS.Model.extend({
titre: DS.attr('string'),
sousTitre: DS.attr('string'),
visuelUrl: DS.attr('string'),
tarifs: DS.hasMany('tarif', { async: true }),
representations: DS.hasMany('representation', { async: true })
});
Problem is: from what I can see (with the ember browser plugin), spectacles and tarifs aren't linked (while spectacles and representations are). The only difference I can find is that they are loaded in two separate server calls, but it shouldn't be an issue, right?
I thought it could be an async/promise issue. My need is, from a representation, to get the first spectacle's tarif. In short: myRepresentation.spectacle.tarifs[0]. I tried various things, like:
representation.get('spectacle.tarifs').then(function(tarifs) {
var tarif = tarifs.get('firstObject');
console.log(tarif);
}
Nothing is working: tarif is always null. Seems that all records are loaded, but the relation between spectacle and tarifs isn't.
Am I doing something wrong?
OK, forget it, the problem was in the tarif model:
App.Tarif = DS.Model.extend({
nom: DS.attr('string'),
montant: DS.attr('number'),
spectacle: DS.belongsTo('spectacle', { async: true })
});
The "belongsTo" relation is a mistake, because a tarif can be linked to many spectacles. I just removed this line, and everything is now fine.
Related
Even though i have set the RESPAdapter to take care of everything, it doesn't reach out to my server to get the data. My code is:
var App = Ember.Application.create({
LOG_TRANSITIONS: true
});
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: '../api/'
});
App.Me = DS.Model.extend({
email: DS.attr('string'),
firstname: DS.attr('string'),
lastname: DS.attr('string')
});
App.WelcomemessageController = Ember.Controller.extend({
firstname:"I get rendered as i should",
model: function() {
return this.store.find('me');
}
});
And yeah, the property "firstname" gets rendered out just fine. And when inspecting with Chrome Devtools, no requests are being made.
In your case you just want to use a computed property, and not the model function. you could call it model, but it'd be slightly confusing since generally a controller decorates a model, and in this case it'd just be a property called model on the controller (in order to decorate a model, the controller needs to be an ObjectController or ArrayController)
App.WelcomemessageController = Ember.Controller.extend({
firstname:"I get rendered as i should",
user: function() {
return this.store.find('me');
}.property()
});
I have got this route retrieving 2 models:
App.PanelRoute = Ember.Route.extend({
model: function(){
var topologymin = this.store.find('topologymin');
var metricmap = this.store.find('metricmap', { param1: 'something'})
return Ember.RSVP.hash({
topologymin: topologymin,
metricmap: metricmap
});
});
This makes 2 calls:
http://localhost/topologymins
http://localhost/metricmaps?param1=something
If I go to another route and again to this one, it makes again the call with the params, not the other one:
http://localhost/metricmaps?param1=something
But, as its the same call to retrieve the same records I would like them to be cached like in the other call.
How does it know when to call the server and when its not necessary? Is it possible to do that?
My models:
App.Topologymin = DS.Model.extend({
siteGroup: DS.attr('string'),
sites: DS.hasMany('site')
});
App.Metricmap = DS.Model.extend({
profile: DS.attr('string'),
link: DS.attr('string'),
services: DS.attr()
});
When you fire a request based on params Ember Data doesn't know how those params necessarily translate into the models (aka it doesn't know that you have all of the records that have some sort of relationship param1). You can cache it yourself, but then you'd still need some sort of way of knowing those records from other records in your store.
App.PanelRoute = Ember.Route.extend({
model: function(){
var met = this.get('fetchedBeforePromise'),
topologymin = this.store.find('topologymin'),
metricmap = met || this.store.find('metricmap', { param1: 'something'});
this.set('fetchedBeforePromise', metricmap);
return Ember.RSVP.hash({
topologymin: topologymin,
metricmap: metricmap
});
});
I have a model that has a one to many relationship with multiple translations:
App.Category = DS.Model.extend({
translation_ids: DS.hasMany('translation', { embedded: 'always' }),
});
App.Translation = DS.Model.extend({
name: DS.attr(),
locale: DS.attr()
});
I want to fetch the name of the category according to the selected language :
App.CategoryController = Ember.ObjectController.extend({
needs: ['settings'],
currentLocale: Ember.computed.alias('controllers.settings.currentLocale'),
name: function() {
var translations = this.get('translation_ids').filterBy('locale', this.get('currentLocale'));
Ember.assert("Only one translation is expected", translations.length === 1);
return translations[0].get('name');
}.property('translation_ids')
});
Everything works out great. But when I edit my category, the "name" property doesn't update :
I have tried a million different things, but nothing work so far. Could someone point out my mistake?
translation_ids is an array, so you want to observe the elements in the array, not just the array itself. Use .property('translation_ids.#each').
I'm trying to build the following view with Ember.js:
Users: (x in total)
* User 1: y Posts
* User 2: z Posts
I've created a itemController that is responsible for getting the number of posts of each user.
App.IndexItemController = Ember.ObjectController.extend({
postCount: function() {
var posts = this.get('content').get('posts');
return posts.get('length');
}.property()
});
Full code on jsbin.
Somehow I always get 0 posts for each user, I guess that is because the relationship is not resolved correctly at this.get('content').get('posts'). What would be the right way to do this? Or am I going a completely wrong way?
Bonus question: What can I pass to the property() and should I pass something to it?
You need to set the dependent keys of your computed property, in your case content.posts.length. So the postCount knows when need to be updated.
App.IndexItemController = Ember.ObjectController.extend({
postCount: function() {
var posts = this.get('content').get('posts');
return posts.get('length');
}.property('content.posts.length')
});
Now your computed property is correct, but no data is loaded, this happen because there isn't posts associated with your users, no in the user -> post direction. So you need to add it in the fixture:
App.User.FIXTURES = [
{
id: 1,
name: 'Jon',
nick: 'Jonny',
posts: [1]
},
{
id: 2,
name: 'Foo',
nick: 'Bar',
posts: [2]
}
];
After this an error is raised Uncaught Error: Assertion Failed: You looked up the 'posts' relationship on '<App.User:ember280:1>' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.hasMany({ async: true })`).
Ember data identified that you have an async relationship, and warns you to setup the property with async: true
App.User = DS.Model.extend({
name: DS.attr('string'),
nick: DS.attr('string'),
posts: DS.hasMany('post', { async: true })
});
This your updated jsbin
SO,
I am working on an Ember app and experiencing a confusing problem. At the index route the app performs a find() and returns an array of dataset and links to a template to show further details about each dataset which are sideloaded when a resquest is made to find by id. (i.e. find(1), where 1 is the id.)
The first request with an id works fine, returning the dataset object and it's sideloaded data, however subsequent requests do not seem to do anything. The server does not see any request if I try to navigate to any other dataset after the first one's details have been loaded. However if I navigate from a specific dataset back to index and then back to any dataset it will send the request again (twice even, am not sure if this a related problem) and work. In other words:
/# works
/#/1 also works (or any other id as long as it is the first one visited)
/#/1 then /#/2 does not work, no request is sent
/#/1 followed by /# then /#/2 does work, maintaining the data at /#/1 & getting the new data for /#/2.
How do I get all of the specific dataset objects to return upon visiting them, without the hacky pitstop at index? Any advice would be greatly appreciated, thank you in advance!
The code:
-app.js
/**************************
* Application
**************************/
var App = Em.Application.create();
App.Router.map(function() {
this.resource('application', {path:'/'}, function() {
this.resource('dataset', {path: '/:dataset_id'}, function() {
});
});
});
App.ApplicationRoute = Em.Route.extend({
model: function() {
return App.Dataset.find();
}
});
App.DatasetRoute = Em.Route.extend({
activate: function() {
this.modelFor('dataset').reload();
}
});
/**************************
* Models
**************************/
App.Store = DS.Store.extend({
adapter: DS.RESTAdapter.create({
url: 'http://***.***.***.***:5000',
namespace: 'api',
serializer: DS.RESTSerializer.extend({
primaryKey: function(type) {
return '_id';
}
})
})
});
App.Dataset = DS.Model.extend({
dataset: DS.attr('string'),
title: DS.attr('string'),
points: DS.hasMany('App.Point')
});
App.Point = DS.Model.extend({
dataset: DS.attr('string'),
dataset_id: DS.attr('string'),
date: DS.attr('date'),
value: DS.attr('string')
});
A route's activate hook is only called when the route is first transitioned to. It is not called again if the route's model changes. So when you transition into App.DatasetRoute either by entering the url directly or by clicking link on index page, the activate hook runs and your dataset is reloaded. When you switch from #/1 to #/2, the route remains active and no hook is called.
If I am understanding your question correctly, you want to reload the dataset whenever a user visits its url. In that case instead of the route's activate hook what you probably want to do is observe changes to the dataset controller's content. Something like this should work:
App.DatasetController = Ember.ObjectController.extend({
refreshOnChange: function() {
var dataset = this.get('content');
if (dataset) {
console.log('reloading dataset ', dataset.toString());
dataset.reload();
}
}.observes('content')
}