DMCoding
DMCoding

Reputation: 1237

Dynamic controllers in Ember.js

I want to make some dynamic controllers based on the top-level keys of a JSON object where the second level keys become variables for the view. Is this possible?

E.g.

App.dat = { "First": {Var1: "x", Var2: "y"}, "Second": {Var3: "z"}}

I then want to have a FirstController, SecondController, etc. created automatically and then be able to access {{Var1}}, {{Var2}} and {{Var3}} in my view.

The routes work fine:

App.Router.map(function() {
  this.route('data');
  for(var key in App.dat) {
    this.route(key);
  }
});

But I can't get the controllers to work. The closest I came was with some hacky eval code:

for(var key in App.dat) {
  console.log("App." + key + "Controller = Ember.Controller.extend();");
  eval("App." + key + "Controller = Ember.Controller.extend();");
  Ember.$.each(eval("App.dat."+key), function(kkey,v) {
    console.log("App." + key + "Controller." + kkey + " = '" + v + "';");
    eval("App." + key + "Controller." + kkey + " = '" + v + "';");
  });
}

That results in the following evaluations:

App.FirstController = Ember.Controller.extend();
App.FirstController.Var1 = "x";
App.FirstController.Var2 = "y";
App.SecondController = Ember.Controller.extend();
App.FirstController.Var2 = "z";

But I'm clearly missing something because I can't access {{x}},{{y}} or {{z}} from the view. I am aware the correct way to instantiate variables for the view is with a constructor object like:

App.FirstController = Ember.Controller.extend({Var1: "x", Var2: "y"});

But that isn't practical and I can't figure out where the constructor object gets stored.

Thanks in advance.

Upvotes: 2

Views: 111

Answers (2)

Pavel Petrov
Pavel Petrov

Reputation: 11

You can override Ember.DefaultResolver's resolveController method. Which is responsible for lookuping controller classes.

App = Ember.Application.create({
  Resolver: Ember.DefaultResolver.extend({
    resolveController: function(parsedName) {
      var props = Ember.get(App.dat, parsedName.name);

      if (!Ember.isNone(props)){
        return Ember.Controller.extend(props);
      }

      return this._super(parsedName);
    }
  })
});

jsbin

Upvotes: 1

DMCoding
DMCoding

Reputation: 1237

After some careful bug hunting, the following code works fine:

for(var key in App.dat) {
  properties = Array();
  Ember.$.each(eval("App.dat."+key), function(kkey,v) {
    properties.push(kkey + ": '" + v + "'")
  });
  console.log("App." + key + "Controller = Ember.ObjectController.extend({" +properties + "})");
  eval("App." + key + "Controller = Ember.ObjectController.extend({"+ properties + "})");
}

Is there a less hacky way to do this than by eval()ing everything? Remember this data comes from JSON, so I can't imagine this would be safe in a real app.

Upvotes: 0

Related Questions