Inside an Ember controller
I have a number of actions
which perform data events (create update and delete) on the store.
Each of these requests has the same error handling logic which is repeated many times. If there a way of centralising this error logic?
this
is still available to send toast type of messages to the DOM ?Here is an example of what I have now
createEntryRecord() {
// This action is a 'create' button on a modal
set(this, 'isLoadingModal', true); // shows loading spinner
let dbid = this.get('dbidModal');
let type = this.get('entryModalType');
this.get('store').createRecord('my-store', {
type,
dbid
})
.save()
.then((record) => {
get(this, 'flashMessages').success(`Created`); // Toast message
})
.catch((e) => {
// Begin of the error handling logic
let errors = get(e, 'errors');
if (errors.length) {
errors.forEach(err => {
let field = err.source.pointer.split("/").pop();
get(this, 'flashMessages').danger(`${field}: ${err.detail}`);
});
} else {
let message = get(e, 'message');
get(this, 'flashMessages').danger(`${message}`);
}
})
.finally(() => {
set(this, 'isLoadingModal', false); // stop the loading spinner
set(this, 'isEntryModalShown', false);
});
},
I would suggest a solution that utilises Ember's Object Model Mixins.
First you create a common Mixin for all your models:
// app/mixins/flashing-model.js
import Mixin from '@ember/object/mixin';
import { inject as service } from '@ember/service';
export default Mixin.create({
flashMessages: service(), // can be accessed via this.get('flashMessages')
save(...args) {
const superSavePromise = this._super(...args);
superSavePromise.then(() => {
// your positive logic
}).catch(e => {
// your negative logic
});
return superSavePromise;
}
});
Then you include it in each of the models. For example:
// app/models/some-model.js
import FlashingModel from '{your-app-name}/mixins/flashing-model';
import DS from 'ember-data'
export default DS.Model.extend(FlashingModel, {
// ...
});
After that you can edit your controller:
this.get('store').createRecord('my-store', {
type,
dbid
})
.save()
.finally(() => {
// ...
});
So regarding your questions:
1. Ember Mixins (under app/mixins
directory) can be a good place to host common logic.
2. When implementing the above solution you don't really need to preserve the controller's this
context, since the flashMessages service is injected to each model. Hence, you can access the service within the save
method's context, which is the this
of model.