0
votes

The workflow is:

  1. User is on the New Page.
  2. Hits save, causing model validations to fail. Errors bound to the model are shown. Still on the same page.
  3. The user now navigates to the Index page and sees the invalid record added to the list.

The ArrayController seems to be adding records which failed validations.

App.CompaniesNewRoute = Ember.Route.extend({

    model: function(){
      var company = App.Company.createRecord();
      this.wireObservers(company, this);
      return company;
    },

    events: {
      save: function(){
        var controller = this.controllerFor(this.routeName);
        controller.get('transaction').commit();
      }
    },

   wireObservers: function(company, router) {
     company.on('becameInvalid', function(record){
      // do something to remove it from the arraycontroller
      // record.rollback();
     });

     company.on('didCreate', function(){
       router.transitionTo('companies.index')
     });
   })
})

The becameInvalid event does get called. Doing a record.rollback() throws an exception:

Uncaught Error: Attempted to handle event `becameClean` on     <App.Company:ember612:null> while in state rootState.loaded.created.invalid. Called with undefined ember-data.js:3495
DS.StateManager.Ember.StateManager.extend.unhandledEvent ember-data.js:3495

Is there a way to prevent ArrayController to add records which failed validation.

2

2 Answers

1
votes

Try to rollback the transaction through the store instead.

   wireObservers: function(company, router) {
     var _self = this;
     company.on('becameInvalid', function(record){
      // do something to remove it from the arraycontroller
       _self.store.rollback();
     });

     company.on('didCreate', function(){
       router.transitionTo('companies.index')
     });
   })

You should consider creating a specific transaction for the purpose rather than using the default one. To create a new transaction inside a route, you can do the following

App.MyRoute = Ember.Route.extend({
    transaction: this.store.transaction();
})

and then create your record and add it to the transaction using

var company = this.transaction.createRecord(App.Company);

and finally commit or rollback the transaction

this.transaction.commit();
this.transaction.rollback();
0
votes

In your case, I think a rollback() is not the solution, because the transaction has already been committed ; even if the server validation fails, the record has been added to the ArrayController content.

The solution I could see would be to use the deleteRecord function, with something like this :

wireObservers: function(company, router) {
 company.on('becameInvalid', function(record){
   record.deleteRecord();
 });

 company.on('didCreate', function(){
   router.transitionTo('companies.index');
 });

})

I've just a question about your workflow. When you get an validation error, and leave the page, it means the user cancelled the record creation