Counting model with ember data - javascript

I've looked at various examples on Stackoverflow but I don't seem to understand how get('length') really works.
I'm trying to get a count of users in helper model. There is probably something wrong with the way I'm trying to get('length'), but maybe I also need to use hash RSVP to get both the current model and helper model in todo route?
todo.js
export default Ember.Controller.extend({
count: function() {
var helper = this.get('helper');
return helper.user.get('length');
}.property('helper.user.[]'),
todo.js
export default DS.Model.extend({
title: DS.attr('string'),
isCompleted: DS.attr('boolean', {defaultValue: false}),
list: DS.belongsTo('list', {async: true}),
user: DS.belongsTo('user', {async: true}),
comment: DS.hasMany('comment', {async: true}),
helper: DS.hasMany('helper', {async: true}),
});
todo.hbs
<p>
<span class="badge pull-left">14 hands</span>
<span class="badge pull-left">{{todo.count}}</span>
</p>
helper.js
export default DS.Model.extend({
user: DS.belongsTo('user', {async: true}),
todo: DS.belongsTo('todo', {async: true}),
});
todo.js
export default Ember.Route.extend({
model: function(params){
// return model
},

User is a single object, so there probably isn't a length property on it. And with async properties you need to access them using promise notation (and a getter as well).
helper.get('user').then(function(user){
console.log(user.get('someProperties'));
})

Related

Not retrieving any information from model using Ember.js using query() method

I'm trying to learn Ember.js by building a web application using the framework for the front end and node.js for the backend as well as mongoDB as a database.
I am using/attempting to use the url to feed in a parameter id and then query on that id.
I am having trouble grabbing the information from my model. My query works fine when I am using findAll(). However, when I switch to find() or query() I can't retrieve any results.
All the documentation I have looked at use different syntax that I have tried but none have worked.
I would greatly appreciate any hint or input. Thank you.
app/router.js
Router.map(function() {
this.route('stock', { path: '/:stock_id' });
});
app/routes/stock.js
export default Ember.Route.extend({
model: function(params) {
this.store.query('stock', {filter:{id : params.stock_id}}).then(function(stock){return stock.get('firstObject')});
}
});
app/models/stock.js
export default DS.Model.extend({
Symbol: DS.attr('string'),
Name: DS.attr('string'),
LastSale: DS.attr('string'),
MarketCap: DS.attr('string'),
IPOyear: DS.attr('string'),
Industry: DS.attr('string')
});
app/serializers/stock.js
export default DS.RESTSerializer.extend({
primaryKey: '_id',
serializeId: function(id) {
return id.toString();
}
});
app/templates/stock.hbs
{{#each model as |item|}}
<h3>{{item.Name}}</h3>
{{/each}}
my nodejs server
app.get('/api/stocks/:id', function(req, res){
StockModel.findOne({'_id': req.params.id},function(err,docs){
console.log(docs.symbol);
if(err){
res.send({error:err});
}
else{
res.send({stock:docs});
}
});
});
Model hook should return the result, only then this will be set in model in corresponding controller through setupController method hook.
model: function(params) {
return this.store.query('stock', {filter:{id : params.stock_id}}).then(function(stock){return stock.get('firstObject')});
}
Update:
Your model field name should be camelCased
// app/models/stock.js
export default DS.Model.extend({
symbol: DS.attr('string'),
name: DS.attr('string'),
lastSale: DS.attr('string'),
marketCap: DS.attr('string'),
iPOyear: DS.attr('string'),
industry: DS.attr('string')
});
and ensure, your backend is accepting the filter and returning the required result in the below format,
"stocks": [
{
"id": 1,
"symbol": "foo",
"name": "foo",
"lastSale": "foo",
"marketCap": "foo",
"iPOyear": "foo",
"industry": "foo"
}]
You need to return the query from the model. Update your app/routes/stock.js to look like
export default Ember.Route.extend({
model(params) {
return this.store
.query('stock', {
filter: {
id: params.stock_id
}
})
.then(stock => stock.get('firstObject'))
}
})

Ember.JS - Cannot filterBy or filter based on computed properties

I'm trying to filter the result of my hasMany-Array async-get with filterBy and condition "isRoot" == true. The "isRoot" property is a computed property and it seems that the filterBy function of ember doesn't wait for the promise to resolve. Here my code:
Model for Directory
App.Directory = DS.Model.extend(App.ModelEventHandler, {
name: DS.attr('string', {defaultValue: ''}),
users: DS.hasMany('user', {async: true}),
isRootOfShare: DS.attr('boolean', {defaultValue: false}),
directories: DS.hasMany('directory', {async: true, inverse: 'directory'}),
directory: DS.belongsTo('directory', {async: true, inverse: 'directories'}),
shares: DS.hasMany('share', {async: true}),
files: DS.hasMany('file', {async: true}),
isRoot: function () {
var directoryPromise = this.get('directory');
return directoryPromise.then(function (directory) {
var isRoot = directory === null;
return isRoot;
}.bind(this));
}.property('directory')}
Model for User
App.User = DS.Model.extend(App.ModelEventHandler, {
// Attributes begin
email: DS.attr('string'),
isCurrentUser: DS.attr('boolean', {defaultValue: false}),
// Relationships
directories: DS.hasMany('directory', {async: true}),
shares: DS.hasMany('share', {async: true}) }
The statement I'm using to filter the directories:
user.get('directories').then(function (directories) {
//TODO: Fix isRoot
var filteredDirectories = directories.filterBy('isRoot', true);
return filteredDirectories;
});
Someone here who knows a solution for my problem? Thx in advance!
UPDATE
I made a JSBIN with shows my current problem. Here the link JSBIN link to my example
I came up with a solution myself. I'm using Ember.computed.equal instead of a computed property.
Here a part of the code
isRoot: Ember.computed.equal('directory.content', null),
Working jsbin example http://jsbin.com/kiwujohefa/1/edit?js,output .
Does somebody know whats the technical difference between a computed property and ember.computed.equal? I thought under the hood they work the same just that ember.computed.equal provides a specific functionality e.g. here equal?

Deleterecord is not deleting object from the HasMany array

I have an event model which has a relationship to a rider model. The event model has a property called riders that is a hasMany of riders and it is also async. The rider model has a property called event that is a belongTo and it contains the proper event that it belongs to. I am loading all of my data from my own REST API that is ran via Node.js and Express 4.
Here is my deletion code:
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
deleteRider: function () {
var model = this.get('model');
var evt = model.get('event');
model.deleteRecord();
model.save().then(function() {
evt.save();
});
}
}
});
models/event.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
city: DS.attr('string'),
state: DS.attr('string'),
date: DS.attr('string'),
riders: DS.hasMany('rider', {
async:true,
inverse:'event'
})
});
models/rider.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
city: DS.attr('string'),
state: DS.attr('string'),
BB: DS.attr('boolean'),
SB: DS.attr('boolean'),
BU: DS.attr('boolean'),
event: DS.belongsTo('event')
});
Im having problems to understand what are u exactly trying to delete.
But the way i approach this is. There's an array of Model instances and there's an array of toDeleteModelInstances. The first array is shown on template using each method. And during the delete of each instance you use toDeleteModelInstancesArray.pushObject(selectedInstance)
Looks something like this.
Delete
deleteFieldset: function(givenRecord){
//remove from Each array then push to array containing deleted records
this.get('controller.markedForDeleted.pushObject(givenRecord));
// You now have a record in given array [class,class]
}
Now on EDIT action
var personsToDelete = self.markedForDeleted.map(function(item){
return item.destroyRecord();
});
// Checks for deletedInstances array
if(Ember.isEmpty(personsToDelete)){
deletePersonSuccess();
} else {
Ember.RSVP.all(personsToDelete).then(deletePersonSuccess, deletePersonFailure);
}

Sideloading only necessary data in ember-data

Here are my model definitions:
var model = DS.Model,
attr = DS.attr,
hasMany = DS.hasMany;
App.Genre = model.extend({
animes: hasMany('anime', {async: true}),
nom: attr('string')
});
App.Anime = model.extend({
nom: attr('string'),
parution: attr('number'),
synopsis: attr('string'),
likes: attr('number'),
auteur: attr('string'),
genres: hasMany('genre', {async: true})
});
as shown in here: http://emberjs.jsbin.com/xakoyipo/3/edit
when I access http://emberjs.jsbin.com/xakoyipo/3#/animes for example.. all the genres gets loaded.. same thing when accessing http://emberjs.jsbin.com/xakoyipo/3#/animes/1
so my question is: how to load only necessary data using ember-data?
It works fine. Take a look at http://emberjs.jsbin.com/xakoyipo/12#/animes I removed the mockjax for genres, in your console you'll see it tries to get emberjs.jsbin.com/api/fr/genres?ids[]=1&ids[]=3. Because ember needs multiple genres it will not request emberjs.jsbin.com/api/fr/genres/1 and emberjs.jsbin.com/api/fr/genres/3 but requests both records in one call.

How to deserialize self many-to-many for ember data

//Setup:
Ember: 1.3.2
Handlebars: 1.3.0
jQuery: 2.0.0
-----------------
MongoDB (_id's, embedded data)
I have been attempting to get a self many to many relationship like this:
//Model:
App.Post = DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string'),
links: DS.hasMany('App.Post'),
});
Links should be embedded as id's for (hopefully) obvious reasons.
After a couple of days digging around I have managed to get the app to serialise and submit the data correctly via RESTAdapter, the code I am using looks like this:
//Controller:
App.PostController = Ember.ObjectController.extend({
actions: {
addRelated: function(related) {
var links = this.content.get('links').pushObject(related);
this.content.save();
}
}
});
//Store:
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.extend({
url: '/admin/api',
serializer: DS.RESTSerializer.extend({
primaryKey: function(type) {
return '_id';
},
addHasMany: function(hash, record, key, relationship) {
if (/_ids$/.test(key)) {
hash[key] = [];
record.get(this.pluralize(key.replace(/_ids$/, ''))).forEach(function(post) {
hash[key].push(post.get('id'));
});
}
return hash;
}
})
});
});
From what I can gather the serializer is expecting data in the form
{post: {...}, links: [{...},{...}]}
But since the link is of type post, I would rather not create an entire App.Links model if possible.
So can I map links to posts? As in
{post: {...}, posts: [{...},{...}]}
I tried adding a deserializeHasMany but it didn't get called when using App.Post.find()
I am guessing I would need to write a custom extract function that takes link_ids and extracts the posts into the record from it?
pI haven't test this but would say:
You should change your model to look like this:
App.Post = DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string'),
links: DS.hasMany('post'), //changed
});
Your JSON should be in the format:
{"posts": [{ "id":3 ... post item .... "links":[3,10]} { "id":4... post item .... "links":[4,11]}]}
All links must be included in the JSON unless already loaded.
My understanding is that you should not have to override the RESTAdapter and RESTSerializer as this should work out of the box - if it doesn't I'd first check ajax and capitalization.

Categories