Definitive addon configuration approach

As a community, I think its very important that we have a definitive, community espoused approach to addon configuration. A convention of sorts that I’ve yet to see anywhere in the docs and have seen done many different ways in different addons.

I personally don’t like environment.js for addon configuration? I don’t know much about require.js, but am very comfortable in Ember. So for me, it was super difficult to figure out how to import Ember files inside enviroment.js and override other Ember files there.

My personal approach is to leverage DI, which to me is an Ember dev’s bread and butter. Let’s go through an example. I am developing a form-library, and I know people might use different I18n tools. So for my form labels, I provide a helper function that makes a call to a function called translate. This function should be easily overridden by the consumers of the addon, so lets expose it over a config object.

In addon_proj/addon/config, export an Ember.Object that holds the config object:

import Ember from 'ember';
export default Ember.Object.extend({
	translate: function(key, options){
		return key;
	}
});

Next, per usual, export from addon_proj/app/config:

import Config from addon_proj/config/config';
export default Config;

Add the config to the DI container via addon_proj/app/initializer:

export default {
	name: 'addon-proj',

	initialize: function(container, app) {
		container.register('config:addon-proj',Config);
	}
};

Expose an easy way to grab the config:

export function injectConfig(objectName){
	return Ember.computed(function() {
		return this.container.lookup('config:' + objectName);
	});
}

Use the translate function in an addon file:

config: injectConfig('addon-proj'),
translatedPlaceholder: function() {
    var myPlaceholder = this.get('placeholder');
    return this.get('config').translate(myPlaceholder);
}.property('placeholder')

Then in the consuming application, all one must do is override the config in consumer_proj/config/addon_proj:

import AddonConfig from 'addon_proj/config/config';
import {myTranslate} from 'consumer_proj/helpers/translate-it';

export default AddonConfig.extend({
	translate: function(key,options){
		return myTranslate(key, options);
	}
});

And then override in consumer_proj/initializers/configure_addon_proj:

import AddonProjConfig from 'consumer_proj/config/addon_proj';
export default {
	name: 'addon-proj-overrides',
	after: 'addon-proj',
	initialize: function(container, app) {
		//a singleton by default
		container.register('config:addon-proj',AddonProjConfig);
	}
};

So the idea is to simply override the container registry with your local version of the config. The addon will use this version. I like this version because it adds a lot of flexibility to the configuration and lets you easily use imports from various places in your Ember app.