EmberJs, ce fameux Framework MVC utilisée par de grandes entreprises (Ex: linkedin, twitch…), permet de créer des interfaces utilisateurs avec une très grande aisance. Mais certaine fois, je me suis retrouvé face à un problème plutôt complexe à résoudre: communiquer avec une API.

Je laisse ici une note à l’attention des gens qui, comme moi, débutent avec EmberJs et qui essaye de le faire cohabiter avec une REST API NodeJs ( + MongoDB ). Si c’est le cas, vous avez peut être été confronté aux mêmes difficultés que moi. Mais après quelques recherche j’ai réussi à résoudre les différentes problématiques rencontrées avec ce Framework de manière pérenne.

Cet article sur le site toptal est en parti la source la plus utile que j’ai trouvée pour répondre à cette problématique.

Le problème

Tout d’abord, il faut savoir que le problème du stack “EmberJs + NodeJs + Mongoose” est principalement le fait que MongoDB via NodeJs renvoie des datas dans un JSON qui ressemble à cela:

[
  {title:'Mon title', isCompleted:true},
  {title:'Mon title 2', isCompleted:false},
  ...
]

… Alors que EmberJs s’attend à recevoir et envoies un JSON qui a cette forme:

todos: [
  {title:'Mon title', isCompleted:true},
  {title:'Mon title 2', isCompleted:false},
  ...
]

Il y a un problème secondaire moins important mais qui pourrait néanmoins vous faire rencontrer certaine difficultés, il s’agit du format de la clef primaire de vos models. Dans notre cas, il s’agit de l’objet _id de mongo qui ne correspond pas à un attribut de type string pour EmberJS.

La solution

Attention, l’erreur serait de changer le format de sorti du JSON au niveau de nodeJS. En effet, imaginez que vous deviez créer en parallèle de emberJs un nouveau client qui accepte encore un format Json différent, vous seriez bien dans la… Fin’ bref !

IL FAUT CHANGER LA FORME DU JSON A LA RECEPTION ET A L’ENVOIE DEPUIS EMBERJS :) !

app/adapters

Commençons par la base: pour communiquer avec notre Api, il faut dire à EmberJs où aller chercher les données et ou les envoyer… Pour cela créons un adaptateur.

$ ember generate adapter application

Voilà à quoi ressemble mon fichier app/adapters/application.js, prenez soin de précisez que vous souhaitez communiquer vos données avec une API REST en changeant le nom de la class initialement JSONAdapter en RESTAdapter.

import DS from 'ember-data';

export default DS.RESTAdapter.extend({
    host: 'api.mydomain.io'
});

Serialize

Maintenant la partie la plus importante… celle qui va permettre à votre application de communiquer parfaitement avec l’API. Le sérializer vous permet de modifier le format du JSON à la réception et à l’envoie.

$ ember generate serializer todo
// todo étant le nom du modèle 

Et voilà à quoi ressemble mon RESTSerializer

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
    primaryKey: '_id',
    // Normaliser la réception des datas
    normalizeResponse(store, primaryModelClass, payload, id, requestType) {

        payload = {
          todos: payload
        };
    
        return this._super(store, primaryModelClass, payload, id, requestType);
        /* Réceptionne le json de votre API et le transforme pour pouvoir être traité par 
        * EmberJs sous la forme suivante:
        * todos: [
        * {},{},... 
        * ]
        */
    },
    // Envoie des datas au serveur sous la forme attendu par l'API
    serializeIntoHash: function(hash, type, record, options) { //Remove root element on save
        Ember.merge(hash, this.serialize(record, options));
    }
});