web-dev-qa-db-fra.com

Gestion des erreurs avec l'adaptateur (maintenant par défaut) Ember Data JSON-API

J'utilise Ember 1.13.7 et Ember Data 1.13.8, qui par défaut utilise la norme JSON-API pour formater les charges utiles envoyées et reçues de l'API.

Je souhaite utiliser Ember Gestion des erreurs intégrée des données afin d'afficher les champs de formulaire "erreur" rouges à l'utilisateur. J'ai formaté mes réponses d'erreur API conformément à la norme JSON-API, par exemple.

{"errors":[
    {
        "title":"The included.1.attributes.street name field is required.", 
        "code":"API_ERR", 
        "status":"400", 
    }
]}

et lorsque j'essaie d'enregistrer mon modèle, le rappel d'erreur est correctement exécuté. Si je regarde dans l'inspecteur Ember je peux voir que la valeur "isError" du modèle est définie sur true mais je ne vois pas comment Ember Data est supposé pour savoir quel champ dans le modèle est celui en état d'erreur? Je vois sur les pages officielles JSON-API ( http://jsonapi.org/format/#errors ) que vous pouvez inclure un Objet "source" dans la réponse d'erreur:

source: un objet contenant des références à la source de l'erreur, incluant éventuellement l'un des membres suivants:

pointeur: un pointeur JSON [RFC6901] vers l'entité associée dans le document de demande [par exemple "/ data" pour un objet de données principal, ou "/ data/attributes/title" pour un attribut spécifique].

paramètre: une chaîne indiquant quel paramètre de requête a provoqué l'erreur.

mais est-ce ce que je devrais faire pour dire Ember Data quels champs il doit marquer comme étant dans un état d'erreur?

Si quelqu'un peut aider à faire la lumière sur ce point, je lui en serais reconnaissant.

Merci.

22
danr1979

Notez que la réponse ci-dessous est basée sur les versions suivantes:

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: -------------------------------

La documentation sur la gestion des erreurs est malheureusement dispersée pour le moment car la façon dont vous gérez les erreurs pour les différents adaptateurs (Active, REST, JSON) est un peu différente.

Dans votre cas, vous souhaitez gérer les erreurs de validation de votre formulaire, ce qui signifie probablement des erreurs de validation. Le format des erreurs spécifié par l'API JSON peut être trouvé ici: http://jsonapi.org/format/#error-objects

Vous remarquerez que l'API spécifie uniquement que les erreurs sont renvoyées dans un tableau de premier niveau composé de errors et que tous les autres attributs d'erreur sont facultatifs. Apparemment, tout ce dont l'API JSON a besoin est le suivant:

{
    "errors": [
     {}
    ]
}  

Bien sûr, cela ne fera vraiment rien, donc pour que les erreurs fonctionnent immédiatement avec Ember Data et JSONAPIAdapter, vous devrez inclure au minimum l'attribut detail et les source/pointer attribut. L'attribut detail est ce qui est défini comme message d'erreur et l'attribut source/pointer l'attribut permet Ember Les données déterminent quel attribut dans le modèle est à l'origine du problème. Donc, un objet d'erreur API JSON valide comme requis par Ember Data (si vous utilisez le JSONAPI qui est maintenant la valeur par défaut) est quelque chose comme ceci:

{
    "errors": [
     {
        "detail": "The attribute `is-admin` is required",
        "source": {
             "pointer": "data/attributes/is-admin"
         }
     }
    ]
}  

Notez que detail n'est pas pluriel (une erreur courante pour moi) et que la valeur de source/pointer ne doit pas inclure de barre oblique de début et le nom de l'attribut doit être barré.

Enfin, vous devez renvoyer votre erreur de validation à l'aide du code HTTP 422 qui signifie "Entité non traitable". Si vous ne renvoyez pas un 422 code puis par défaut Ember Les données renverront un AdapterError et ne définiront pas les messages d'erreur sur le hachage errors du modèle. Cela m'a mordu pendant un certain temps parce que j'utilisais le code HTTP 400 (Bad Request) pour renvoyer les erreurs de validation au client.

La façon dont les données ember différencient les deux types d'erreurs est qu'une erreur de validation renvoie un objet InvalidError ( http://emberjs.com/api/data/ classes/DS.InvalidError.html ). Cela entraînera le hachage errors sur le modèle, mais ne définira pas le drapeau isError sur true (vous ne savez pas pourquoi c'est le mais il est documenté ici: http://emberjs.com/api/data/classes/DS.Model.html#property_isError ). Par défaut, un code d'erreur HTTP autre que 422 entraînera le renvoi d'un AdapterError et l'indicateur isError défini sur true. Dans les deux cas, le gestionnaire de rejet de la promesse sera appelé.

model.save().then(function(){
    // yay! it worked
}, function(){
    // it failed for some reason possibly a Bad Request (400)
    // possibly a validation error (422)
}

Par défaut, si le code HTTP renvoyé est un 422 et vous avez le format d'erreur JSON API correct, vous pouvez accéder aux messages d'erreur en accédant au hachage des erreurs du modèle où les clés de hachage sont vos noms d'attribut. Le hachage est saisi sur le nom de l'attribut au format camelcase.

Par exemple, dans notre exemple d'erreur json-api ci-dessus, s'il y a une erreur sur is-admin vous accéderez à cette erreur comme ceci:

model.get('errors.isAdmin');

Cela renverra un tableau contenant des objets d'erreur dont le format est le suivant:

[
   {
      "attribute": "isAdmin",
      "message": "The attribute `is-admin` is required"
    }
]

Essentiellement, detail est mappé sur message et source/pointer est mappé sur attribute. Un tableau est renvoyé si vous avez plusieurs erreurs de validation sur un seul attribut (l'API JSON vous permet de renvoyer plusieurs erreurs de validation plutôt que de renvoyer uniquement la première validation à échouer). Vous pouvez utiliser les valeurs d'erreur directement dans un modèle comme celui-ci:

{{#each model.errors.isAdmin as |error|}}
    <div class="error">
      {{error.message}}
    </div>
{{/each}}

S'il n'y a pas d'erreur, ce qui précède n'affichera rien, donc cela fonctionne bien pour faire des messages de validation de formulaire.

Si votre API n'utilise pas HTTP 422 code pour les erreurs de validation (par exemple, s'il utilise 400), vous pouvez modifier le comportement par défaut de JSONAPIAdapter en remplaçant la méthode handleResponse dans votre adaptateur personnalisé. Voici un exemple qui renvoie un nouvel objet InvalidError pour tout code d'état de réponse HTTP qui est 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);
  }
});

Dans l'exemple ci-dessus, je vérifie si l'état HTTP est 400 et en vérifiant qu'une propriété errors existe. Si c'est le cas, je crée un nouveau DS.InvalidError et retournez-le. Cela se traduira par le même comportement que le comportement par défaut qui attend un 422 Code d'état HTTP (c'est-à-dire que votre erreur d'API JSON sera traitée et le message placé dans le hachage des erreurs sur le modèle).

J'espère que cela pourra aider!

87
Sarus