I am using Ember 1.13.7 and Ember Data 1.13.8, which by default use the JSON-API standard to format the payloads sent to and received from the API.
I would like to use Ember Data's built-in error handling in order to display red "error" form fields to the user. I have formatted my API error responses as per the JSON-API standard, e.g.
{"errors":[
{
"title":"The included.1.attributes.street name field is required.",
"code":"API_ERR",
"status":"400",
}
]}
and when I attempt to save my model the error callback is being correctly executed. If I look within the Ember Inspector I can see that the model's "isError" value is set to true but I can't see how Ember Data is supposed to know which field within the model is the one in an error state? I see from the official JSON-API pages (http://jsonapi.org/format/#errors) that you can include a "source" object within the error response:
source: an object containing references to the source of the error, optionally including any of the following members:
pointer: a JSON Pointer [RFC6901] to the associated entity in the request document [e.g. "/data" for a primary data object, or "/data/attributes/title" for a specific attribute].
parameter: a string indicating which query parameter caused the error.
but is this what I should be doing in order to tell Ember Data which fields it should mark as being in an error state?
If anyone can help shed some light on this I'd be grateful.
Thanks.
Note the answer below is based on the following versions:
The error handling documentation is unfortunately scattered around at the moment as the way you handle errors for the different adapters (Active, REST, JSON) are all a bit different.
In your case you want to handle validation errors for your form which probably means validation errors. The format for errors as specified by the JSON API can be found here: http://jsonapi.org/format/#error-objects
You'll notice that the API only specifies that errors are returned in a top level array keyed by
errors
and all other error attributes are optional. So seemingly all that JSON API requires is the following:Of course that won't really do anything so for errors to work out of the box with Ember Data and the JSONAPIAdapter you will need to include at a minimum the
detail
attribute and thesource/pointer
attribute. Thedetail
attribute is what gets set as the error message and thesource/pointer
attribute lets Ember Data figure out which attribute in the model is causing the problem. So a valid JSON API error object as required by Ember Data (if you're using the JSONAPI which is now the default) is something like this:Note that
detail
is not plural (a common mistake for me) and that the value forsource/pointer
should not include a leading forward slash and the attribute name should be dasherized.Finally, you must return your validation error using the HTTP Code
422
which means "Unprocessable Entity". If you do not return a422
code then by default Ember Data will return anAdapterError
and will not set the error messages on the model'serrors
hash. This bit me for a while because I was using the HTTP Code400
(Bad Request) to return validation errors to the client.The way ember data differentiates the two types of errors is that a validation error returns an
InvalidError
object (http://emberjs.com/api/data/classes/DS.InvalidError.html). This will cause theerrors
hash on the model to be set but will not set theisError
flag to true (not sure why this is the case but it is documented here: http://emberjs.com/api/data/classes/DS.Model.html#property_isError). By default an HTTP error code other than422
will result in anAdapterError
being returned and theisError
flag set totrue
. In both cases, the promise's reject handler will be called.By default if the HTTP code returned is a
422
and you have the correct JSON API error format then you can access the error messages by accessing the model's errors hash where the hash keys are your attribute names. The hash is keyed on the attribute name in the camelcase format.For example, in our above json-api error example, if there is an error on
is-admin
your would access that error like this:This will return an array containing error objects where the format is like this:
Essentially
detail
is mapped tomessage
andsource/pointer
is mapped toattribute
. An array is returned in case you have multiple validation errors on a single attribute (JSON API allows you to return multiple validation errors rather than returning just the first validation to fail). You can use the error values directly in a template like this:If there are no errors then the above won't display anything so it works nicely for doing form validation messages.
If you API does not use the HTTP
422
code for validation errors (e.g., if it uses400
) then you can change the default behavior of the JSONAPIAdapter by overriding thehandleResponse
method in your custom adapter. Here is an example that returns a newInvalidError
object for any HTTP response status code that is400
.In the above example I'm checking to see if the HTTP status is
400
and making sure an errors property exists. If it does, then I create a newDS.InvalidError
and return that. This will result in the same behavior as the default behavior that expects a422
HTTP status code (i.e., your JSON API error will be processed and the message put into the errors hash on the model).Hope that helps!