ember.js - jsonapiadapter - Manejo de errores con el(ahora predeterminado) adaptador Ember Data JSON-API
jsonapiadapter ember (1)
Estoy usando Ember 1.13.7 y Ember Data 1.13.8, que por defecto usan el estándar JSON-API para formatear las cargas útiles enviadas y recibidas desde la API.
Me gustaría utilizar el manejo de errores integrado de Ember Data para mostrar al usuario los campos rojos de "error". He formateado mis respuestas de error de API según el estándar JSON-API, p. Ej.
{"errors":[
{
"title":"The included.1.attributes.street name field is required.",
"code":"API_ERR",
"status":"400",
}
]}
y cuando intento guardar mi modelo, la devolución de llamada de error se está ejecutando correctamente. Si miro dentro del Inspector de ascuas, puedo ver que el valor "isError" del modelo está establecido en verdadero, pero no puedo ver cómo se supone que Ember Data sabe qué campo dentro del modelo es el que está en estado de error. Veo en las páginas oficiales de JSON-API ( http://jsonapi.org/format/#errors ) que puede incluir un objeto "fuente" dentro de la respuesta de error:
fuente: un objeto que contiene referencias a la fuente del error, que incluye opcionalmente cualquiera de los siguientes miembros:
puntero: un puntero JSON [RFC6901] a la entidad asociada en el documento de solicitud [por ejemplo, "/ data" para un objeto de datos primario, o "/ data / atributos / título" para un atributo específico].
parámetro: una cadena que indica qué parámetro de consulta causó el error.
pero, ¿es esto lo que debería hacer para decirle a Ember Data qué campos debe marcar como en estado de error?
Si alguien puede ayudar a arrojar algo de luz sobre esto, estaría agradecido.
Gracias.
Tenga en cuenta que la respuesta a continuación se basa en las siguientes versiones:
DEBUG: -------------------------------
ember.debug.js:5442DEBUG: Ember : 1.13.8
ember.debug.js:5442DEBUG: Ember Data : 1.13.9
ember.debug.js:5442DEBUG: jQuery : 1.11.3
DEBUG: -------------------------------
Desafortunadamente, la documentación de manejo de errores está dispersa en este momento, ya que la forma en que maneja los errores para los diferentes adaptadores (Active, REST, JSON) es un poco diferente.
En su caso, desea manejar los errores de validación de su formulario, lo que probablemente significa errores de validación. El formato para los errores según lo especificado por la API JSON se puede encontrar aquí: http://jsonapi.org/format/#error-objects
Notarás que la API solo especifica que los errores se devuelven en una matriz de nivel superior con clave de
errors
y todos los demás atributos de error son opcionales.
Aparentemente, todo lo que requiere la API JSON es lo siguiente:
{
"errors": [
{}
]
}
Por supuesto, eso realmente no hará nada, por lo que para que los errores funcionen de fábrica con Ember Data y el adaptador JSONAPIA, deberá incluir como mínimo el atributo de
detail
y el atributo de
source/pointer
.
El atributo de
detail
es lo que se establece como mensaje de error y el atributo de
source/pointer
permite que Ember Data descubra qué atributo en el modelo está causando el problema.
Por lo tanto, un objeto de error de API JSON válido según lo requerido por Ember Data (si está utilizando JSONAPI, que ahora es el predeterminado) es algo como esto:
{
"errors": [
{
"detail": "The attribute `is-admin` is required",
"source": {
"pointer": "data/attributes/is-admin"
}
}
]
}
Tenga en cuenta que los
detail
no son plurales (un error común para mí) y que el valor de la
source/pointer
no debe incluir una barra inclinada hacia adelante y el nombre del atributo debe ser discontinuo.
Finalmente, debe devolver su error de validación utilizando el Código HTTP
422
que significa "Entidad no procesable".
Si no devuelve un código
422
, de forma predeterminada, Ember Data devolverá un
AdapterError
y no establecerá los mensajes de error en el hash de
errors
del modelo.
Esto me mordió por un tiempo porque estaba usando el Código HTTP
400
(Solicitud incorrecta) para devolver errores de validación al cliente.
La forma en que ember data diferencia los dos tipos de errores es que un error de validación devuelve un objeto
InvalidError
(
emberjs.com/api/data/classes/DS.InvalidError.html
).
Esto hará que se establezca el hash de
errors
en el modelo, pero no establecerá el indicador
isError
en verdadero (no estoy seguro de por qué es así, pero está documentado aquí:
http://emberjs.com/api/data/classes/DS.Model.html#property_isError
).
Por defecto, un código de error HTTP que no sea
422
dará como resultado que se
AdapterError
un
AdapterError
y que el indicador
isError
establezca en
true
.
En ambos casos, se llamará al controlador de rechazo de la promesa.
model.save().then(function(){
// yay! it worked
}, function(){
// it failed for some reason possibly a Bad Request (400)
// possibly a validation error (422)
}
De manera predeterminada, si el código HTTP devuelto es
422
y tiene el formato de error JSON API correcto, puede acceder a los mensajes de error accediendo al hash de errores del modelo donde las claves hash son sus nombres de atributos.
El hash está tecleado en el nombre del atributo en el formato camelcase.
Por ejemplo, en nuestro ejemplo de error json-api anterior, si hay un error en
is-admin
accedería a ese error de esta manera:
model.get(''errors.isAdmin'');
Esto devolverá una matriz que contiene objetos de error donde el formato es así:
[
{
"attribute": "isAdmin",
"message": "The attribute `is-admin` is required"
}
]
Esencialmente, los
detail
se asignan al
message
y la
source/pointer
se asigna al
attribute
.
Se devuelve una matriz en caso de que tenga múltiples errores de validación en un solo atributo (la API JSON le permite devolver múltiples errores de validación en lugar de devolver solo la primera validación que falla).
Puede usar los valores de error directamente en una plantilla como esta:
{{#each model.errors.isAdmin as |error|}}
<div class="error">
{{error.message}}
</div>
{{/each}}
Si no hay errores, lo anterior no mostrará nada, por lo que funciona bien para hacer mensajes de validación de formularios.
Si su API no usa el código HTTP
422
para errores de validación (por ejemplo, si usa
400
), puede cambiar el comportamiento predeterminado del adaptador JSONAPIA anulando el método
handleResponse
en su adaptador personalizado.
Aquí hay un ejemplo que devuelve un nuevo objeto
InvalidError
para cualquier código de estado de respuesta HTTP que sea
400
.
import DS from "ember-data";
import Ember from "ember";
export default DS.JSONAPIAdapter.extend({
handleResponse: function(status, headers, payload){
if(status === 400 && payload.errors){
return new DS.InvalidError(payload.errors);
}
return this._super(...arguments);
}
});
En el ejemplo anterior, verifico si el estado HTTP es
400
y me aseguro de que exista una propiedad de errores.
Si es así, creo un nuevo
DS.InvalidError
y lo devuelvo.
Esto dará como resultado el mismo comportamiento que el comportamiento predeterminado que espera un código de estado HTTP
422
(es decir, su error de API JSON se procesará y el mensaje se colocará en el hash de errores en el modelo).
¡Espero que ayude!