Ember-Data callback when findAll finished loading all records - ember.js

With ember-data I'm loading all records of a model with:
App.adapter = DS.Adapter.create({
findAll: function(store, type) {
var url = type.url;
jQuery.getJSON(url, function(data) {
var ids = data.map(function(item, index, self){ return item.id });
store.loadMany(type, ids, data);
});
}
});
The didLoad method is called when each of the record has finished loading. Is there a method to call when all records have finished loading?
EDIT
Model:
App.Article = DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string'),
checkIsLoaded: function() {
if (this.get('isLoaded')){
console.log('loaded!'); // outputs `loaded` for each record
}
}.observes('isLoaded')
});

Yes, you can use findQuery, and then observe .isLoaded property on the ModelArray.
e.g:
load: ->
#set 'data', #get('store').findQuery App.MyModel, { q: '...' }
And have the observation:
loadingComplete: ( ->
#doSomeStuff() if #getPath 'data.isLoaded'
).observes 'data.isLoaded'

Related

ember data array UI not updating on pushObject

I have a list of product-tag that I fetch for my model.
Route:
model: function() {
return {
product_tags: this.store.find('product-tag', {merchant: merchId})
}
}
I have a component that adds tags to the model, however when after I create the record and push it into the model (as suggested on other posts) my UI still isn't updating.
addTag: function(name) {
tag = this.store.createRecord('product-tag', {
name: name
});
this.model.product_tags.toArray().addObject(tag);
tag.save();
}
//model merchant.js
export default DS.Model.extend({
user_id: DS.attr('number'),
product_tags: DS.hasMany('product-tag', {async: true})
});
//model product-tag.js
export default DS.Model.extend({
merchant: DS.belongsTo('merchant'),
name: DS.attr('string'),
});
What am I doing wrong? Thanks in advance.
You should make it array in the route, so u can use it always afterwards like u want. Your calling toArray() which makes a new Array instance, then your model is not hooked to the array u just made.
model: function() {
return {
product_tags: this.store.query('product-tag', {merchant: merchId}).then(function(pt) {
return pt.toArray();
});
}
}
var x = this.get('model.product_tags') === model's p_t // true
var y = this.get('model.product_tags').toArray() === model's p_t // false
Later on just do
addTag: function(name) {
this.get('store').createRecord('product-tag', {
name: name
}).save().then(function(saved){ 
this.get('model.product_tags').pushObject(saved);
}.bind(this);
}

Ember-Data store.filter with async relationships

I am working on a survey application and we are using an existing API. Our models look like:
App.User = DS.Model.extend({
name: DS.attr('string'),
participations: DS.hasMany('participation', {async: true})
});
App.Participation = DS.Model.extend({
user: DS.belongsTo('user', {async: true}),
survey: DS.belongsTo('survey', {async: true}),
hasCompleted: DS.attr('boolean'),
hasAccepted: DS.attr('boolean')
});
App.Survey = DS.Model.extend({
participations: DS.hasMany('participation', {async: true}),
title: DS.attr('string'),
locked: DS.attr('boolean')
});
I would like to return a live record array from my model hook via store.filter however this filter needs to deal with both survey's and the async participant record for the current user. How can I handle the async relation resolution in my filter callback function?
model: function() {
return Ember.RSVP.hash({
user: this.store.find('user', 1),
surveys: this.store.filter('survey', {}, function(survey) {
return !survey.get('locked'); //How do I get the participation record for the current user for the current poll so I can also filter out the completed true
})
});
}
If using a live record array of survey's is not the best way to deal with this what is?
Edit:
I've updated the approach to try:
App.SurveysRoute = Ember.Route.extend({
model: function() {
return Ember.RSVP.hash({
user: this.store.find('user', 1),
all: this.store.find('survey'),
locked: this.store.filter('survey', function(survey) {
return survey.get('locked');
}),
completed: this.store.filter('participation', {user: 1}, function(participation) {
return participation.get('hasCompleted');
}),
outstanding: this.store.filter('participation', {user: 1}, function(participation) {
return !participation.get('hasCompleted') && !participation.get('poll.locked');
})
});
}
});
App.SurveysCompletedRoute = Ember.Route.extend({
model: function() {
return this.modelFor('surveys').completed.mapBy('survey');
}
});
http://jsbin.com/vowuvo/3/edit?html,js,output
However, does the usage of the async property participation.get('poll.locked') in my filter pose a potential problem?
Had originally written my response in ES6 and ember-cli format, while localising Ember references... please excuse if this is a touch basic as I reverted it to ES5 and used commonly understood code structure for Ember.
Try this:
// beforeModel() and model() are skipped if coming from a collection
// ie: from '/users' to '/users/1'
// setting this up is purely for direct linking to this route's path.
model: function(params) {
return this.store.findRecord('user', params.id).then(function(user) {
return user.get('participations');
});
},
// only fired once!
// soon to be obsolete...
setupController: function(controller, model) {
controller.set('model', model);
var store = this.store,
userId, availSurveys, completed, outstanding;
store = this.store;
userId = model.get('id');
// this is a promise!
// also, these filters can be applied elsewhere that Store is available!
availSurveys = store.filter(
// modelName to be filtered.
'surveys',
// this part is the query - sent as a request to server, not used as a filter
{ locked: false },
// this is the active filter that will be applied to all survey records in client,
// updating 'availSurveys' as the records change
function(survey) {
return !survey.get('locked');
});
completed = store.filter('participation',
{
user : userId,
hasCompleted : true
},
function(participation) {
return participation.get('hasCompleted');
});
outstanding = store.filter('participation',
{
user : userId,
hasCompleted : false,
survey : { locked: false }
},
function(participation) {
// this is also a promise!
return participation.get('survey').then(function(survery) {
return !participation.get('hasCompleted') && !survey.get('locked');
});
});
// alternatively, hashSettled waits until all promises in hash have resolved before continuing
Ember.RSVP.hash({
availSurveys : availSurveys,
completed : completed,
outstanding : outstanding
}).then(function(hash) {
controller.set('availSurveys', hash.availSurveys);
controller.set('completed', hash.completed);
controller.set('outstanding', hash.outstanding);
});
}

Model is empty after update but data is saved to the database and shown on reload

I'm updating a model using the following controller:
payment_controller.js
App.PaymentNewController = Ember.ObjectController.extend({
needs: ['student'],
isNew: true,
actions: {
createPayment: function() {
var date = new Date(this.get('date'));
if (!date) { return false; }
var amount = this.get('amount');
if (!amount) { return false; }
var studentId = this.get('controllers.student.id');
if (this.isNew)
{
var payment = this.store.createRecord('payment', {
date: date,
amount: amount,
});
}
else
{
var payment = this.get('model');
payment.set('date', date);
payment.set('amount', amount);
}
var self = this;
var onSuccess = function(payment) {
self.set('date', '');
self.set('amount', '');
self.transitionToRoute('student', studentId);
};
var onFail = function(payment) {
};
if (this.isNew)
{
this.store.find('student', studentId).then(function(student){
payment.set('student', student);
payment.save().then(onSuccess, onFail);
});
}
else
{
payment.save().then(onSuccess, onFail);
}
},
}
});
The data returned from the server is the following, and it looks in the correct format expected by ember:
{"payment":{"amount":1111,"date":"2014-09-09T00:00:00.000Z","student":"54024bb9cd52254e181325af","_id":"54024bdacd52254e181325b0"}}
The issue is that after saving the data is correctly saved to the database, but in the store is empty (UPDATE: except the id). As soon as I reload the page the data is shown correctly and is the updated version of the model. This made me think to the fact that the error could lie in the response of the PUT request, but it looks fine to me.
I've been trying many different things with no success. I can provide additional code or info if needed.
UPDATE 1
Here are the involved routes:
App.StudentsRoute = Ember.Route.extend({
model: function() {
return this.store.find('student');
}
});
App.StudentRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('student', params.student_id);
}
});
App.StudentEditRoute = Ember.Route.extend({
setupController: function(controller, model) {
this.controllerFor('student.new').setProperties({isNew:false, content:model});
},
renderTemplate: function() {
this.render('student/new');
}
});
App.PaymentNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('payment');
}
});
App.PaymentEditRoute = Ember.Route.extend({
setupController: function(controller, model) {
this.controllerFor('payment.new').setProperties({isNew:false, content:model});
},
renderTemplate: function() {
this.render('payment/new');
}
});
UPDATE 2
Here are the serializer and the adapter:
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://localhost:3000',
});
App.ApplicationSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
primaryKey: '_id',
serializeId: function(id) {
return id.toString();
},
attrs: {
payments: {embedded: 'always'},
lessons: {embedded: 'always'}
}
});
UPDATE 3
Here are the models:
App.Student = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
email: DS.attr('string'),
nationality: DS.attr('string'),
dateOfBirth: DS.attr('date'),
payments: DS.hasMany('payment'),
lessons: DS.hasMany('lesson'),
});
App.Payment = DS.Model.extend({
student: DS.belongsTo('student'),
date: DS.attr('date'),
amount: DS.attr('number'),
});
UPDATE 4
While inspecting the store using the Ember Inspector in Chrome I've noticed that after the update is completed, the only property that contains data in the payment object (in the store) is the id. Both date and amount are empty.

Implementing model filter

I have set up the following scaffolding for my Ember application.
window.App = Ember.Application.create({});
App.Router.map(function () {
this.resource('coaches', function() {
this.resource('coach', {path: "/:person_id"});
});
});
App.ApplicationAdapter = DS.FixtureAdapter.extend({});
App.Person = DS.Model.extend({
fname: DS.attr('string')
,lname: DS.attr('string')
,sport: DS.attr('string')
,bio: DS.attr('string')
,coach: DS.attr('boolean')
,athlete: DS.attr('boolean')
});
App.Person.FIXTURES = [
{
id: 10
,fname: 'Jonny'
,lname: 'Batman'
,sport: 'Couch Luge'
,bio: 'Blah, blah, blah'
,coach: true
,athlete: true
}
,{
id: 11
,fname: 'Jimmy'
,lname: 'Falcon'
,sport: 'Cycling'
,bio: 'Yada, yada, yada'
,coach: false
,athlete: true
}
];
I am trying to set up a route to filter the person model and return only coaches. Just to make sure I can access the data, I have simply used a findAll on the person model.
App.CoachesRoute = Ember.Route.extend({
model: function() {
return this.store.findAll('person');
}
});
Now though, I am trying to implement the filter method detailed on the bottom of the Ember.js Models - FAQ page.
App.CoachesRoute = Ember.Route.extend({
model: function() {
var store = this.store;
return store.filter('coaches', { coach: true }, function(coaches) {
return coaches.get('isCoach');
});
}
});
The coaches route is not working at all with the new route implemented and the old one commented out. I am using the Ember Chrome extension and when using the filter route the console responds with, Error while loading route: Error: No model was found for 'coaches'. Apparently the route is not working, specifically the model. No kidding, right? What am I missing in my filter model route?
Thank you in advance for your help.
The error message is spot on- there is no CoachModel. I think you need to do this:
App.CoachesRoute = Ember.Route.extend({
model: function() {
var store = this.store;
return store.filter('person', { coach: true }, function(coaches) {
return coaches.get('isCoach');
});
}
});

Ember.js access model values

I'd like to be able to modify/validate data before actually saving.
Model
App.Post = DS.Model.extend({
title: DS.attr('string'),
author: DS.attr('string'),
date: DS.attr('date', { defaultValue: new Date() }),
excerpt: DS.attr('string'),
body: DS.attr('string')
});
Route
App.PostsNewRoute = Ember.Route.extend({
model: function() {
return this.get('store').createRecord('post');
},
actions: {
doneEditing: function() {
debugger;
this.modelFor('postsNew').save();
this.transitionTo('posts.index');
}
}
});
So, the questions, before the .save() I want to, let's say, validate that the title is not empty or so.
Everything I've tried gets undefined, or [Object object] has no .val() method. I don't know how to get to the values of the model. How can I do that?
And the other thing I have in mind. Is that defaultValue working as intended? I want to set Date() to every new created post. Somehow date is not being recorded since it's not showing.
Thanks.
App.PostsNewRoute = Ember.Route.extend({
model: function() {
return this.get('store').createRecord('post');
},
actions: {
doneEditing: function() {
debugger;
var model = this.modelFor('postsNew');
var title = model.get('title');
model.save();
this.transitionTo('posts.index');
}
}
});