1

I am creating an application in Ember that needs to be easily replicated with slight variations on different sites. What I'd like to do is, essentially, have my Ember app read a config file and then adjust itself accordingly.

In my case, I only need to change one controller and an accompanying template. In this question, I am tackling the controller only.

I need to add properties to a controller dynamically that can then be called in a template.

How would I go about doing that?

Don
  • 746
  • 6
  • 18

1 Answers1

1

Here's what I came up with:

var propertiesConfig = [
  {name: 'newFunction1', arbitraryType: 'monkeys',         numThings: 6 },
  {name: 'newFunction2', arbitraryType: 'daysOfChristmas', numThings: 7 },
  {name: 'newFunction3', arbitraryType: 'monkeys',         numThings: 8 },
  {name: 'newFunction4', arbitraryType: 'daysOfChristmas', numThings: 9 },
  {name: 'newFunction5', arbitraryType: 'monkeys',         numThings: 10 },
  {name: 'newFunction6', arbitraryType: 'daysOfChristmas', numThings: 11 },
  {name: 'newFunction7', arbitraryType: 'monkeys',         numThings: 12 }
];

var MonkeyFunctionBuilder = function(buildData){
  return function(){
    if (buildData.numThings == 12) return 'Brad Pitt';
    return buildData.numThings + ' monkeys';
  }
};

var ChristmasDaysFunctionBuilder = function(buildData){
  return function(){
    return buildData.numThings + ' ' + daysOfChristmas[buildData.numThings]
  }
};

var passedObject = {};
for(var i = 0; i < propertiesConfig.length; i++){
  switch(propertiesConfig[i].arbitraryType){
    case 'monkeys':
      passedObject['monkeys'+propertiesConfig[i].numThings] = 
        new MonkeyFunctionBuilder(propertiesConfig[i]).property();
      break;
    case 'daysOfChristmas':
      passedObject[propertiesConfig[i].name] = 
        new ChristmasDaysFunctionBuilder(propertiesConfig[i]).property();
      break;
  }
}; 

App.AnyController.reopen(passedObject);

The propertiesConfig represents my config file mentioned in the question.

I found that I needed to create the builder functions (actually Classes, if I am not mistaken) to keep the values on already created properties from getting updated whenever i changed inside my for loop. These functions' names need to start with a CaptialLetter, not the normal uncapitalized first letter that is mostly seen in javascript code.

MonkeyFunctionBuilder uses only the data found inside the config object to build the function. ChristmasDaysFunctionBuilder uses data from the daysOfChristmas object that was declared somewhere else in the application. In theory, that could be called from an API so that your application can be altered from an external set of data as well. Be careful: security, etc.

Note also that when using a variable to declare or get the data from the name of a property on any object, you have to use brackets (object[variableName]) instead of the normal dot notation (object.variableName). Found that out from another question on StackOverflow.

In the final block of code where you see the loop, you can do whatever you need to do to manipulate your data. In my example, I am choosing to use propertiesConfig[i].name to declare some of the App.AnyController property names, and then propertiesConfig[i].numThings (along with the keyword monkey) to declare the others.

The result inside the Ember Debugger on the AnyController looks like this:

screenshot of Ember Debugger results

Community
  • 1
  • 1
Don
  • 746
  • 6
  • 18
  • The reopen statement here is the only thing that has to do with Ember and the answer to the question you actually asked. The method you use to digest your 'propertiesConfig' and generate the object you pass into the reopen statement is up to you. It's very hard to know your requirements or the context of what your trying to achieve in this code because you didn't really explain it in your initial question or this answer. :/ – Aaron Storck Apr 04 '14 at 01:10
  • I didn't even know enough to be able to ask a question about what I needed. I wanted to add properties to a controller in Ember at runtime, based on a config file. The file would give me a type and a name and I would need to create any number of properties that did any number of things (based on type) and have them all named in a way that I'd know how to access them in a template. – Don Feb 27 '15 at 10:44