I'm trying to convert Ember-Data Model instances to an array with the goal of loading it into an Handsontable (http://handsontable.com). The toArray() method does not seems to convert the attributes of the StatVals Model to an Array but to create an Array of StatVals objects. How to properly construct an Array from a Ember-Data Model Attributes?
Further, I want the new array to contain the time and element and not the other attributes of the statVal model. How should I approach this?
The View that construct the Handsontable:
App.chapterView = Ember.View.extend({
tagName: 'div',
classNames: ['dataTable'],
insertTable: function(){
var divElement = jQuery('.dataTable');
var data = this.get('controller.model.statVals').toArray();
divElement.handsontable({ data: data });
}.on('didInsertElement')
});
Model:
App.Chapter = DS.Model.extend({
name: DS.attr('string'),
createdDate: DS.attr('date'),
statVals: DS.hasMany('statVal', { inverse: 'chapter', async: true}),
user: DS.belongsTo('user', { inverse: 'chapter', async: true} )
});
App.StatVal = DS.Model.extend({
time: DS.attr('date'),
Element: DS.attr('number'),
Chapter: DS.belongsTo('chapter'),
user: DS.belongsTo('user', { inverse: 'statVals', async: true} )
});
I found the below related questions but I'm not convince that they present the best approach to my situation:
ember-data as data for d3
What is the Ember way of converting retrieved Ember Data records into plain objects?
Simply removing the statVals in var data = this.get('controller.model.statVals').toArray(); enabled me to feed the Handsontable table with data from Ember-Data. The complete View code is:
App.chapterView = Ember.View.extend({
tagName: 'div',
classNames: ['dataTable'],
insertTable: function(){
var divElement = jQuery('.dataTable');
var data = this.get('controller.model').toArray();
divElement.handsontable({ data: data });
}.on('didInsertElement')
});
Related
I have a model "Group" that has some hasMany relationships "members" and "links". I have a controller that adds a new group but i get the following error on save
"Assertion Failed: A App.Group record was pushed into the store with the value of links being '{}', but links is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer."
I can fix this by returning an empty links array in the response json but i don't necessarily want this included and i don't understand why i get this error for links but not for members as that isn't included in the response either.
App.AddGroupController = Ember.ObjectController.extend({
needs: ['application'],
actions: {
submitForm: function(){
var self = this;
var model = this.get('model');
self.send('showLoading', 'Saving');
model.save().then(function(){
self.send('hideLoading');
//Go to the groups list
self.transitionToRoute('groups');
},function(error){
self.send('hideLoading');
console.log(error);
//Must supply reject callback, otherwise Ember will throw a 'backend rejected the commit' error.
});
}
}
});
App.AddGroupRoute = App.AuthenticatedRoute.extend({
model: function(){
return this.store.createRecord('group');
}
});
App.Group = DS.Model.extend({
title: DS.attr('string'),
description: DS.attr('string'),
members: DS.hasMany('groupMember'),
links: DS.hasMany('groupLink'),
});
App.GroupLink = DS.Model.extend({
title: DS.attr('string'),
link: DS.attr('string'),
});
App.GroupMember = DS.Model.extend({
first_name: DS.attr('string'),
last_name: DS.attr('string'),
email: DS.attr('string'),
profile_picture: DS.attr('string'),
});
Response from save:
{
"group":{
"id":26,
"title":"Test Group",
"description":"Dummy group description",
}
}
Im using:
Ember : 1.9.1
Ember Data : 1.13.14
I'm trying to set up the attributes to my model but having trouble when nesting objects. Here is what I have
App.Posts = DS.Model.extend({
title: DS.attr('string'),
author: {
name: DS.attr('string')
},
date: DS.attr('date'),
excerpt: DS.attr('string'),
body: DS.attr('string')
});
How am I suppose to declare the author object?
In the ember inspector when I go under data and under App.post and select one of the rows. It has a property a property App.Post with an attribute author: { name: [Object] }
here is the JS Bin link http://jsbin.com/tesozepexaqi/2/
Ember works perfectly fine without Ember Data. Let's pretend we want to do it with Ember Data:
Ember Data's Records should be flat. This means all properties are at the top level. If you have a related data that exist deeper they generally live in a different record. If you're attempting to embed the record you'll need to look into the tricky world of embedded records (Ember-data embedded records current state?). At the very least these related records must have an id defined. So here's an example of what the data returned from server should look like.
{
posts:[
{
id: '1',
title: 'My name is Django.',
author: {
id:1,
name: 'D name'
},
date: new Date('08-15-2014'),
excerpt: 'The D is silent.',
body: 'The D is silent.'
},
{
id: '2',
title: 'White horse',
author: {
id:2,
name: 'horse name'
},
date: new Date('08-15-2014'),
excerpt: 'Is what I ride.',
body: 'My horse likes to dance.'
}
]
}
Code
App.ApplicationAdapter = DS.RESTAdapter.extend();
App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
author: {embedded: 'always'}
}
});
App.Post = DS.Model.extend({
title: DS.attr('string'),
author: DS.belongsTo('author'),
date: DS.attr('date'),
excerpt: DS.attr('string'),
body: DS.attr('string')
});
App.Author = DS.Model.extend({
name: DS.attr()
});
Example: http://jsbin.com/vazada/1/edit
One other small tip, you'll not want to use globals when working with the routes, you can use modelFor to get the model from a different route.
App.PostsRoute = Ember.Route.extend({
model: function() {
return this.store.find('post');
}
});
App.PostRoute = Ember.Route.extend({
model: function(params) {
var posts = this.modelFor('posts');
return posts.findBy('id', params.post_id);
}
});
Personally, I think Ember Data is overkill. Ember works perfectly well with POJOs. If you need caching and the ability to rollback then Ember Data might be a good solution for you.
Example: http://jsbin.com/vazada/2/edit
Adjusting this example from the Ember docs like the below should work:
App.Post = DS.Model.extend({
title: DS.attr('string'),
author: DS.belongsTo('author'),
date: DS.attr('date'),
excerpt: DS.attr('string'),
body: DS.attr('string')
});
App.Author = DS.Model.extend({
post: DS.belongsTo('post')
})
Below is the code I am using to get data from web API. But every time I try to retrieve data I get same error: Unable to set property 'store' of undefined or null reference in ember.js.
/// <reference path="Lib/ember.js" />
/// <reference path="Lib/ember-data.js" />
var App = Ember.Application.create();
Ember.onerror = function(e) {
alert(e);
};
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api'
});
App.store = DS.Store.create({
adapter: App.ApplicationAdapter
});
App.Product = DS.Model.extend({
ID: DS.attr("int"),
Name: DS.attr('string'),
Category: DS.attr('string'),
});
App.ApplicationRoute = Ember.Route.extend({
model: function() {
{{debugger}}
var store1 = this.get("store")
var k = store1.find('product', 1)
return k;
}
});
Your problem is with the returned json from the server. You need to return the following object:
{
product: {
// key value
}
}
If you want to use the DS.RESTAdapter defaults, you can just return the data in that format:
{
product: {
id: 1,
name: 'some name',
category: 'some category'
}
}
And change your model mapping to:
App.Product = DS.Model.extend({
name: DS.attr('string'),
category: DS.attr('string'),
});
If you want to use the capitalized properties like Name, Category. You will need to override some methods of DS.RESTAdapter. If your endpoing doesn't match this format.
Other error is that doesn't exist a DS.attr('int') just DS.attr('number'). But you can remove the id mapping, since is created by default.
This is a jsfiddle with this working http://jsfiddle.net/marciojunior/W5LEH/
Ensure that you are using last versions of Ember.js and Ember-Data.
This is how you define a store for you application:
App.Store = DS.Store.extend({
adapter: App.ApplicationAdapter
});
Note the capital S in Store and extend instead of create.
See Ember-Data Guide
I would get the records of my field children. Here the code:
App.User = DS.Model.extend({
name: DS.attr('string'),
online: DS.attr('boolean')
});
App.List = DS.Model.extend({
name: DS.attr('string'),
children: DS.hasMany('App.User'),
online: function() {
var users = this.get("children");
return users.reduce(0, function(previousValue, user){ // no record founds
return previousValue + user.get("online");
});
}.property("children.#each.online")
});
But App.List.find(1).get('online') returns no record. (For some reason I cannot specify that App.List.children contains many records, of type App.Users, as embedded records).
Here is the fiddle: JSBIN and it's output
How I can solve my issue?
Define the embedded Model on your Adapter map:
App.List = DS.Model.extend({
name: DS.attr('string'),
users: DS.hasMany('App.User'), //use "users" as the property name to mantain ember's naming conventions
...
});
App.Adapter = DS.RESTAdapter.extend();
App.Adapter.map('App.List', {
users: {embedded: 'always'} //you can use `always` or `load` which is lazy loading.
});
App.Store = DS.Store.extend({
revision: 12,
adapter: App.Adapter.create()
});
Hope it helps
I am trying to migrated my app to using Ember-Data as it's persistence mechanism. One thing that strikes me is that I'm not sure if it's still possible to use an arrayProxy for aggregate properties of a hasMany association. In my previous iteration I didn't have any explicit associations, just controllers tied together by specific properties. Now I'd like to take advantage of the association functionality in ember-data, but I am getting errors when I trie to bind the content of my array proxy to the "children" property of the DS.Model. My code is below and there is a jsfiddle here: http://jsfiddle.net/sohara/7p6gb/22/
The error I get is:
Uncaught TypeError: Object App.recipeController.content.ingredients has no method 'addArrayObserver'
I would like to be able to retain a controller layer, even if the data associations are controlleed at the model level. It'd also (ideally) like the child objects to be embedded in the json representation of the parent object in order to avoid multiple server requests.
window.App = Ember.Application.create();
App.store = DS.Store.create({
revision: 3,
adapter: DS.fixtureAdapter
});
App.Ingredient = DS.Model.extend({
name: DS.attr('string'),
price: DS.attr('string')
});
App.Recipe = DS.Model.extend({
name: DS.attr('string'),
ingredients: DS.hasMany('App.Ingredient', {embedded: true} )
});
App.Recipe.FIXTURES = [
{id: 1, name: 'Pizza', ingredients: [{id: 1, name: 'tomato sauce', price: 2, recipeId: 1}]}
];
App.recipeController = Ember.Object.create({
content: App.store.find(App.Recipe, 1)
});
App.ingredientsController = Ember.ArrayProxy.create({
content: 'App.recipeController.content.ingredients',
totalWeigth: function() {
var price = 0;
items = this.get('content');
items.forEach(function(item) {
weight += price;
});
}.property()
});
In App.ingredientsController you need to have contentBinding: 'App.recipeController.content.ingredients', instead of content: ...