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);
}
Related
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'))
}
})
This has been asked a couple times, but the examples didn't help a whole lot.
I want to post 'posts' to my server, so I have a 'posts' model and then a 'single' model. The 'posts' model represents all the posts, and then my 'single' model represents what each post needs... I am new to Ember.js, and really could use a hand here/direction.
So when I submit the form (for creating a new post):
// When the form is submitted, post it!
actions: {
// createNew begin
createNew() {
var title = this.controller.get('title');
var content = this.controller.get('content');
const data = {
"posts": [
{
"title": title,
"content": content
}
]
};
return this.store.createRecord('posts', data).save().
then(function(post) {
console.log(post);
}, function(error) {
console.log(error);
});
} // end of createNew
}
'posts' model:
import DS from 'ember-data';
export default DS.Model.extend({
posts: DS.hasMany('single'),
});
'single' model:
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string'),
});
And then my serializer to hook the two together...
import DS from 'ember-data';
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
posts: { embedded: 'always' }
}
});
Currently, this is the error that outputs:
"Assertion Failed: All elements of a hasMany relationship must be instances of DS.Model, you passed [[object Object]]"
In Short: I need to create data models that can represent the following JSON structure:
{
"posts": [
{ "title": "Title", "content": "Content" }
]
}
Thanks!
The error is actually saying exactly what's wrong.
"Assertion Failed: All elements of a hasMany relationship must be instances of DS.Model, you passed [[object Object]]"
The model posts has a hasMany relationship to the model single.
What your code is doing is passing a plain JS object instead of the model.
const data = {
"posts": [
{ // <-
"title": title, // <-
"content": content // <- this is a POJO
} // <-
]
};
One way to solve this actually is to create the two objects separately.
// create 'posts' and 'single' separately
const posts = this.store.createRecord('posts');
const single = this.store.createRecord('single', {
title,
content
});
// link them up
posts.get('posts').addObject(single);
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'));
})
I'm writing an ember-cli app. I have the following model:
// app/models/school.js
export default DS.Model.extend({
name: DS.attr('string', { defaultValue: '' })
});
It was generated using an ember generator like all my other models. It has a functioning unit test as well that tests for the default value of it's name attribute. All tests are green until another model belongs to school like this:
// app/models/professor.js
export default DS.Model.extend({
name: DS.attr('string', { defaultValue: '' }),
email: DS.attr('string', { defaultValue: '' }),
courses: DS.hasMany('course'),
posts: DS.hasMany('post'),
school: DS.belongsTo('school')
});
This test is totally green until I add the school attribute. It's even green with 'model:school' defined in the needs array of the moduleForModel helper:
// tests/unit/models/professor-test.js
// this is green w/o belongsTo('school') in the model
moduleForModel('professor', {
// Specify the other units that are required for this test.
needs: ['model:school', 'model:post', 'model:course']
});
The error I'm getting is:
Error: No model was found for 'school'
Here's the models directory
$ ls app/models/
course.js post.js professor.js school.js student.js
Why is it not finding my model?
You need to import the school model in your test:
import '[appName]/models/school';
//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.