I'm using ember(+data) and have built a simple signup form, but I'm having trouble getting the form (and ember-data transaction) to work properly after a server-side validation error.
I'm following https://github.com/dgeb/ember_data_example as a guide for how to use transactions, and it mostly works for the Happy Path, but after a server-side validation error, I can't get ember-data to resubmit the API request when I click Submit.
I did some digging around, and I think I'm missing some step related to resetting the transaction after the model becomes invalid or something like that...
You can try the app and reproduce the problem at http://emb.herokuapp.com/
You can also examine the full source code at https://github.com/justinfaulkner/ember-data-resubmit
You can trigger a fake server-side error by completing the form in my app using an e-mail address at @example.com. The Rails API will respond 422 and an errors object keyed to the username/email field.
The field should be highlighted in red with an error -- edit the email address to something that should be valid, and click Submit again. With developer tools open in chrome, I don't see ember-data sending an http request with the click (but a console.log in the controller indicates that the click is indeed being received).
After modifying the field with the error, ember-data (I think) changes the model's from invalid
to uncommitted
so that it gets submitted the next time commit
is called. When I click Submit, ember-data should send the HTTP request to my api, and ember should transition to the "Congrats!" page.
Instead, however, the form just sits there. No http request. No transition to "Congrats!".
Here's a screenshot after I clicked Submit a few (18) times after having updated the inputs:
Here are some snippets of my ember app:
My route, which uses startEditing
like ember_data_example does:
App.IndexRoute = Ember.Route.extend({
model: function() {
return null;
},
setupController: function(controller) {
controller.startEditing();
},
deactivate: function() {
this.controllerFor('index').stopEditing();
}
});
My IndexController
is modeled after ember_data_example's ContactsNewController
App.IndexController = Ember.ObjectController.extend({
startEditing: function() {
this.transaction = this.get('store').transaction();
this.set('content', this.transaction.createRecord(App.User));
},
submit: function(user){
console.log("submitting!");
this.transaction.commit();
this.transaction = null;
},
_transitionOnSuccess: function(stuff) {
if (this.get('content.id') && this.get('content.id').length > 0) {
console.log("_transitionOnSuccess");
this.transitionToRoute('success');
}
}.observes('content.id'),
stopEditing: function() {
if (this.transaction) {
this.transaction.rollback();
this.transaction = null;
}
}
});
Here's my model. I'm using ember-validations.
App.User = DS.Model.extend(Ember.Validations.Mixin);
App.User.reopen({
username: DS.attr('string'),
password: DS.attr('string'),
profile: DS.belongsTo('App.Profile'),
validations: {
username: {
presence: true
},
password: {
presence: true,
length: { minimum: 6 }
}
}
});
And here's the form from my handlebars template. I'm using ember-easyForm.
{{#formFor controller}}
<div class="row">
<div class="large-12 columns">
{{input username placeholder="Email address"}}
</div>
</div>
<div class="row">
<div class="large-12 columns">
{{input password placeholder="Password"}}
</div>
</div>
{{submit "Sign Up" class="button"}}
{{/formFor}}
In case the library authors see this post, I have made a couple local modifications to the app's copy of ember-easyForm and ember-validations in this commit: https://github.com/justinfaulkner/dockyard-example/commit/f618b0e4fb72314d56bb3a9d95e1325925ba6ad0 . I don't think my changes are causing my problem, though.
I did run across a similar-looking question here: Ember Data and dirty records but when I added a User.becameInvalid
to rollback the transaction, this caused the form to empty when trying to re-submit (and still no success having ember-data resubmit the http request).
I'm sure I'm following ember_data_example
poorly (or failing to extend it to my use-case) or am making some simple mistake somewhere...
Thanks in advance.
So far, I can find at least two main problems:
this.transaction = null;
Do I need this? What should I do instead?this.transaction = null;
and ember-data tries to actually commit now (but still won't submit the ajax request). Now, when I type in the invalid field, I can see ember-data try to update the record back to uncommitted
/created
... but it does it in a different transaction.I pushed up a no-null
branch to the repo that has some console.log
s in ember-data that prints out what the transaction ID is... here's a snapshot of my console:
recordBecameDirty
is called when I type in the field. Ember-data updates the record to be ready to be committable again. But, it's doing it in some other transaction (458)
But my submit button is tied to the original transaction (316), and there's no records ready to commit in that transaction.... hmm....
This is a known issue with ember data. See: https://github.com/emberjs/data/pull/539
The simple change in Ember Data in that commit https://github.com/Cyril-sf/data/commit/fe9c63beb02e9f16051e59a9f7c0a918152a0231 should solve your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With