Table des matières

Opérations CRUD

Store

Récupération du store, dans un contrôleur ou un route handler :

let store=this.get('store');

Read : chargement d'enregistrements

1 enregistrement

Chargement d'une instance de person

let person = this.get('store').findRecord('person', 1);

Recherche d'une instance de person déjà chargée (ne retourne que si elle est déjà présente dans le store, sans effectuer de requête vers le serveur) :

let person = this.get('store').peekRecord('person', 1);

Plusieurs enregistrements

Chargement de toutes les instances de person :

let persons = this.get('store').findAll('person');

Retour des instances de person déjà chargée dans le store :

let persons = this.get('store').peekAll('person');

Recherche par critères

De plusieurs enregistrements

this.get('store').query('person', {
  filter: {
    name: 'Peter'
  }
}).then(function(peters) {
  // Do something with `peters`
});

D'un seul enregistrement

this.get('store').queryRecord('person', {
  filter: {
    id: 1234
  }
}).then(function(user) {
  // Do something with `user`
});

Create

Toutes les opérations de modification (ajout, modification, suppression) fonctionnent en 2 étapes :

Création d'une instance

let post = store.createRecord('post', {
  title: 'Rails is Omakase',
  body: 'Lorem ipsum'
});

Mise à jour de la création (persistance) :

post.save();

Update

Mise à jour de l'instance avec setter et persistance :

this.get('store').findRecord('person', 1).then(function(tyrion) {
  // ...after the record has loaded
  tyrion.set('firstName', 'Yollo');
  tyrion.save();
});

Delete

Suppression d'une instance et persistance :

  post.deleteRecord();
  post.get('isDeleted'); // => true
  post.save(); // => DELETE to /posts/1

Il est possible d'utiliser destroyRecord pour effectuer directement la suppression :

  post.destroyRecord();

Flags, dirty attributes et annulation

Tant que la méthode save n'est pas appelée, la persistance n'est pas réalisée, et les instances modifiées portent les flags mentionnant leurs modifications :

person.get('isAdmin');            // => false
person.get('hasDirtyAttributes'); // => false
person.set('isAdmin', true);
person.get('hasDirtyAttributes'); // => true
person.changedAttributes();       // => { isAdmin: [false, true] }

Il est possible d'annuler les modifications avec rollbackAttributes tant que l'appel de la méthode save n'a pas été effectué.

person.get('hasDirtyAttributes'); // => true
person.changedAttributes();       // => { isAdmin: [false, true] }

person.rollbackAttributes();

person.get('hasDirtyAttributes'); // => false
person.get('isAdmin');            // => false
person.changedAttributes();       // => {}

Erreurs de validation

Côté router, il est possible d'utiliser le error hook pour intercepter les erreurs de chargement/mise à jour,

import Route from '@ember/routing/route';

export default Route.extend({
  model(params) {
    return this.get('store').findAll('privileged-model');
  },

  actions: {
    error(error, transition) {
      if (error.status === '403') {
        this.replaceWith('login');
      } else {
        // Let the route above this handle the error.
        return true;
      }
    }
  }
});

Si le serveur retourne des erreurs de validation au moment du save, la propriété errors du model permet de les afficher :

{{#each post.errors.title as |error|}}
  <div class="error">{{error.message}}</div>
{{/each}}
{{#each post.errors.body as |error|}}
  <div class="error">{{error.message}}</div>
{{/each}}

Il existe également un loading event permettant d'intervenir sur le chargement :

import Route from '@ember/routing/route';

export default Route.extend({
  ...
  actions: {
    loading(transition) {
      let start = new Date();
      transition.promise.finally(() => {
        this.get('notifier').notify(`Took ${new Date() - start}ms to load`);
      });

      return true;
    }
  }
});

Promises

Toutes les méthodes du store interrogeant le serveur (find, findAll, query, save…) retournent une “promise” permettant d'intercepter la fin du chargement, ou les erreurs éventuelles.

let persons=this.get('store').findAll('person').then(function(datas){
    //les données datas sont chargées
    }).catch(function(reason){
    //Erreurs de chargement
    });

let post = store.createRecord('post', {
  title: 'Rails is Omakase',
  body: 'Lorem ipsum'
});

let self = this;

function transitionToPost(post) {
  self.transitionToRoute('posts.show', post);
}

function failure(reason) {
  // handle the error
}

post.save().then(transitionToPost).catch(failure);