1

While trying to handle server side errors in Ember application, I am unable to show the errors in templates as the model is not populated with the received errors.

Versions used:
Ember-cli: 2.4.3
Ember-data: 2.4.2
adapter: RESTAdapter

The template file contains the form for user sign-up as shown:

    {{input type="text" value=username }}  
    {{#each model.errors.username as |error|}}  
         {{error.message}}  
    {{/each}}  
    {{input type="text" value=email }}  
    <button {{action 'register'}}>Register</button>  

The routes file contains the action 'register' to save the user:

register: function(){  
    var username = this.controller.get('username');  
    var email = this.controller.get('email');  
    var user = this.store.createRecord('user',{  
            email: email,  
            username: username  
        });  
    user.save().then(function(){  
        //handle success  
     },function(error){  
       //handle error  
     });  
 }); 

The model looks like:

export default Model.extend({  
    email: attr(),  
    username: attr()  
}); 

The API I am using responds with a status 422 and error as shown:

{    
   "errors":[  
      {  
         "detail":"can't be blank",
         "source":{  
            "pointer": "/data/attributes/username"
         }
      }
   ]
}  

According to the docs of DS.Errors Errors can be displayed by accessing their property name to get an array of all the error objects for that property. And that is what I am trying to do in my template file.
Also I tried accessing the messages property on the error object without success.

{{#each model.errors.messages as |message|}}
    {{message}}
{{/each}}

When I try to log in console the length property on errors i.e

 user.save().then(function(){  
        //handle success  
     },function(error){  
       //handle error  
       console.log(user.get('errors.length'));
     }); 

It always gives me 0. However

console.log(user.get('errors.username.length'));  

gives the desired output, but still the errors are not visible in the template.
Tried overriding ajaxError in RESTAdapter as mentioned in this post 24027053 but no luck.
I don't know what I am doing wrong. Please Help!

Community
  • 1
  • 1

3 Answers3

1

Solved the problem by setting up the model with the errors. Looks like DS.Errors doesn't set up the model after the errors get populated.

Now my register function looks like:

var route = this;
user.save().then(function(){  
        //handle success  
     },function(error){  
       var errors = user.get('errors');
       route.set('_model.errors',errors);
     });

and the model hook in routes file is:

_model:{},
model(){
return this.get('_model');
}

The register function populates the _model with the errors and the model hook returns _model so that it is available in the views.

1

I don't know if it is the best way but this is what worked for me:

        save(model) {
        model.save()
        .then(() => {
            console.log('success');
        })
        .catch(() => {
            if (model.get('errors.messages.length') > 0) {
                model.get('errors.messages').forEach((message) => {
                    console.log(message);
                });
            } else {
                console.log('failed');
            }
        });
    }

In the template I could access the errors via

{{#each model.errors.messages as |error|}}
  <div class="error">
    {{error}}
  </div>
{{/each}}
HappyDude
  • 310
  • 3
  • 11
  • 1
    This was a problem in earlier versions that the errors were not populated correctly in the model and so they were not accessible in templates. However in later, the problem has been fixed. – Raman Kumar Sharma Nov 03 '17 at 05:14
0

I think the error lies within:

user.save().then(function(){  
    //handle success  
 },function(error){  
   //handle error  
   console.log(user.get('errors.length'));
 }); 

The user is not saved, therefore it has no error. Try this:

 user.save().then(function(){  
    //handle success  
 },function(error){  
   //handle error --> how do you handle it? Are you maybe overriding the default behaviour?
   // you might want to put a 'debugger;' statement here in order to see, what the response actually looks like  
   console.log(error.errors);
 }); 
Remi Smirra
  • 2,499
  • 1
  • 14
  • 15
  • I am not overriding default behaviour, actually I am unable to implement the default behaviour. As I have mentioned twice in my question that the problem is in displaying errors in template. console.log(user.get('errors.username')); gets the error for username also error.errors fetches the desired result. But they can't be displayed in template. model.errors.username , model.errors or simply errors.username doesn't display anything. – Raman Kumar Sharma Oct 18 '16 at 05:01