why does my emberjs model throw an exception when i try calling deleteRecord on it - ember.js

I am doing this tutorial and just when i thought i got everything right, I came across this exception
JavaScript runtime error: Object doesn't support property or method 'deleteRecord'
in this context
removeTodo: function () {
var todo = this.get('model');
todo.deleteRecord();
todo.save();
}
i trying to follow the getting started tutorial on the Ember.js site.

It would appear that your model isn't actually a DS.Model (assuming that you're using Ember Data). Unless you're model is an actual record I'm ember, you won't be able to call delete record.

Related

uncaught typeerror: model.save() is not a function - Emberjs 1.13.8

I am new to ember.js, I am trying to save the model from another contoller where i have am able to get all the information of the model. Whenever i try to save the model using the code below
saveModel: function(model) {
model.save();
},
I am getting this error
Uncaught TypeError: model.save is not a function
Any idea how to solve this error?
Model information is getting passed from components using this.sendAction().
this.sendaction() should be CamelCase -> this.sendAction()
Check the Ember Guides for Components -> Handling Events to make sure you are using this.sendAction() correctly
Make sure by debugging that model is being passed correctly from the component.
Had the same error.
Using _internalModel works but is an ugly solution. My mistake was binding the model to the promise
this.set('prop', this.get('store').findRecord('model', id))
and not use
this.get('store').findRecord('user', this.selectedUser.id).then(function(model) {
self.set('prop', model);
});
Hope that this helps someone having the same problem.

Ember Data error when deleting model

I have an Ember-cli app (v2.1), and I'm having an issue with Ember Data when deleting a record from my blog model. Here's the code I'm calling for the deletion:
deleteBlog (blog) {
this.store.findRecord('blog', blog.get('id')).then(blog => {
blog.destroyRecord();
});
}
As expected, Ember Data makes the DELETE request, which works perfectly with my express.js backend service.
The only problem is that the record does not get removed from the Ember Data store, and I get the following error message:
Error: Attempted to handle event pushedData on my-app#model:blog::ember529:56455037f9cf29a325ae72b9 while in state root.deleted.inFlight
I appreciate any feedback!
The problem was in trying to select the model using an instance of the model that I already had. Changing it to a simple:
deleteBlog (blog) {
blog.destroyRecord();
}
got rid of the error! Thanks again to #torazaboro for helping me to take a closer look at the mistake.
Try this:
deleteBlog (blog) {
this.store.findRecord('blog', blog.get('id')).then(function(blog) {
blog.deleteRecord(); // => remove blog from the store
blog.save(); // => DELETE request
});
}
But this is supposed to do the same as blog.destroyRecord(); so it may not work.
What is probably happenning is that if you have a request to the server in-flight and you delete the model then you get an exception Attempted to handle event pushedData on model while in state root.deleted.uncommitted.

Ember DS.Store.findAll() returns empty collection

Hey I need to modify some records which I get from the DataStore. If I add the following code in my router I can see that the requests get passed to my template, but I can't modify each request of the collection because the collection is empty.
model() {
return this.store.findAll('user').then(function(users) {
console.log(users.get('length')); // 0
return users;
});
}
I thought that the promise gets resolved when all the records have been fetched from the server but this doesn't seem to be the case. Or did I completely miss something.
I also tried to modify the model in the afterModel callback with the same result.
I'm using Ember 1.13.0 (with Ember-CLI), Ember-Data 1.13.4 and ember-cli-mirage for Mocking my HTTP Requests.
UPDATE:
I managed to create a workaround for this issue. In my controller, I created a new property which listens for model.#each and then I was able to modify model and pass it to the view.
export default Ember.Controller.extend({
users: function() {
return this.get('model.users').filter(function(user) {
// The Promise is resolved twice
// The first time with an empty model and the second time with
// the actual data. So I filter the empty model.
return user.get('id');
}).map(function(user) {
// do fancy stuff with our user
return user
});
}.property('model.#each')
});
Ember Data 1.13
So after spending some time on this topic i found the solution to this issue. It's basically the way how ember works. So under the hood findAll is returning two promises.
findAll without data in the store
find records from the store (resolve first promise -> length 0,
because no data is in the store)
fetch new data in the background (resolves second promise)
findAll with data in the store
find records from the store (resolve first promise with cached data)
fetch new data in the background (resolves second promise with new
data)
If you want to wait for all the data to be loaded you can use query which is returning only one promise.
model() {
return this.store.query('user', {});
}
For findRecord I found the following workaround, which is only working if your backend supports any kind of filtering on the id of your record.
model() {
return this.store.query('user', {
'filter[id]': 1
}).then((users) => {
return users.objectAt(0);
});
}
You can have a look on the following discussion on github
Ember Data 2.0
On Ember Data 2.0 this issue is resolved.
First you should make sure the data is coming in from Mirage as you expect. Open your Ember inspector and verify the models made it into your store. If not, you likely have a problem with the format of the JSON response from your mock route.
To diagnose, check out your console for a log of the JSON response, and ensure it matches what you expect. If you have a custom route handler in your /mirage/config.js for this route, you could also put a debugger statement in there and verify the data is what you think it should be.
If you're using default Ember Data 1.13, it probably means you're using the JSON API serializer/adapter. Is this what you intend? What is the backend for this app ultimately going to look like? If it's going to be JSON API, you'll need to do a bit more work in the Mirage config.js file for now, something like
this.get('/contacts', function(db, request) {
return {
data: db.contacts.map(attrs => {
type: 'contacts',
id: attrs.id,
attributes: attrs
})
};
});
I had a similar problem to the one you are describing when using Ember and Ember data version 1.13. At the time, I was reading the updated documentation of Ember 2.0 without Ember Data 2.0. Once I upgraded both libraries I was able to get the behavior you are trying to achieve with the first code snippet. Namely, the promise is handled correctly with nonzero records with ember data 2.0.

Nested routes: handling failed child find in error action loses parent context

I've recently been porting a number of Ember apps I maintain to RC 8 and ran into this.
Before the router facelift landed I would sometimes manage control flow via promises returned by Ember Data find calls.
For example:
SomeRoute = Ember.Route.extend({
model: function(params) {
var resolve = function(model) { return model; };
var route = this;
var reject = function() { this.transitionTo('someOtherRoute'); };
return SomeModel.find(params.some_model_id).then(resolve, reject);
}
...
});
With the recent changes, it is now possible to handle errors created in model callbacks via the error action:
SomeRoute = Ember.Route.extend({
// note: model callback no longer needed--default suffices
actions: {
error: function(reason, transition) {
// check the reason object to determine how/if to handle this error
this.transitionTo('someOtherRoute');
}
}
...
});
I much prefer the latter approach as it makes the code easier to read and better separates concerns.
This works well in most cases but I encountered an issue in an app that uses nested routes. I've included a simplified example followed by a jsbin that demonstrates the issue.
Lets say we want to show Articles that belong to Authors and the URLs look like: /authors/:author_slug/articles/:article_slug. We want to redirect to a Not Found page when someone tries to view an article that doesn't exist.
When managing control flow in the model callback as above, you can browse to /authors/some_author/articles/some_invalid_slug and be redirected to /authors/some_author/articles/not_found as expected.
However, if the redirect to the Not Found page is instead managed via the error action, the parent context is lost at some point and you end up at /authors/undefined/articles/not_found.
You can see this in the following jsbins:
http://jsbin.com/eJOXifo/1#/authors/schneier/articles/12345
(redirects to http://jsbin.com/eJOXifo/1#/authors/schneier/articles/not_found)
http://jsbin.com/oNaWelo/1#/authors/schneier/articles/12345
(redirects to http://jsbin.com/oNaWelo/1#/authors/undefined/articles/not_found)
Does anyone know why this happens or how to avoid it?
Notes:
I know this doesn't have anything to do with Ember Data. However, implementing something equivalent without Ember Data just makes the example more complicated without adding anything
There are a few small hacks to make Ember Data work as expected in jsbin:
I'm preloading the parent model to avoid having to load it from anywhere.
I'm not doing anything special to provide data for the child model. The app just makes a request to http://jsbin.com/articles/12345. This actually returns a 200 but bombs anyway because the response is html. An API that correctly returns a 404 response gives the same behvaiour.
I remember a while ago reading about some service that could be used to build fake API responses for use with services like jsfiddle or jsbin. If anyone knows what it is please comment.
Your right that the parent context is getting lost. The trick is to extract that context from the transition and pass it as an argument when calling transitionTo. So:
App.ArticlesArticleRoute = Em.Route.extend({
actions: {
error: function(reason, transition) {
console.log('in error handler');
this.transitionTo('articles.notFound', transition.resolvedModels.authors);
}
}
});
With this change, visiting the url:
http://jsbin.com/iVOYEvA/2#/authors/schneier/articles/my-fake-article
will redirect to:
http://jsbin.com/iVOYEvA/2#/authors/schneier/articles/not_found

Ember Transaction has no method add

I'm attempting to create an ember transaction to commit a single model to the backend api.
Coffeescript:
comic = App.Comic.createRecord(title: #get('comicTitle'))
transaction = comic.get('store').transaction
transaction.add(comic)
transaction.commit()
Which gives the javascript error:
Uncaught TypeError: Object function () {
return DS.Transaction.create({ store: this });
} has no method 'add'
I've googled various different ways to use ember transactions, but I'm not sure where I'm going wrong. I'm using the latest version of ember data.
The coffeescript to js translation may not be happening correctly. Try changing to
transaction = #get('store').transaction()
I have found the implicit method invocation in coffeescript trips up in Ember occasionally.