How do I DRY up this common ember data loader?


#1

I often find myself doing sth like this:

  this.controllerFor('application').incrementProperty('saving');
  someModel.save().finally(() => {
    this.controllerFor('application').decrementProperty('saving');
  });

If saving > 0 I can show some kind of loading… / saving… element.

In non ember apps I often used some global before and after callbacks (can’t remember the exact details). What’s the best way to tap into sth similar from Ember?


#2

OK here’s what I came up with in my ApplicationController:

import Ember from 'ember';
import $ from 'jquery';

export default Ember.Controller.extend({
  init() {
    this._super(...arguments);

    $(document)
      .ajaxSend((event, jqXHR, settings) => {
        if (settings.type === "GET") {
          console.log("getting ", settings);
          this.incrementProperty('loadingObjectsCount');
        } else {
          this.incrementProperty('savingObjectsCount');
        }
      })
      .ajaxComplete((event, jqXHR, settings) => {
        if (settings.type === "GET" && this.get('loadingObjectsCount') > 0) {
          this.decrementProperty('loadingObjectsCount');
        } else {
          // DELETE, POST, PUT, PATCH ..
          if (this.get('savingObjectsCount') > 0) {
            this.decrementProperty('savingObjectsCount');
          }
        }
      });
  }
});

#3

This seems like it should be an adapter concern.

There are already some ember addons that handle this automatically for you, if they aren’t what you need (and it looks like they are) then maybe see their source for some inspiration?

https://emberobserver.com/categories/loading-indicators


#4

i would consider the following changes:

  1. create a service instead of storing this state on the application controller

  2. reopen DS.Model class and override the save method. not sure whether injection works in models, so use the getOwner and lookup APIs to access your service. if you can’t get the service in the model, then this approach won’t work.