4
votes

Let's say I have an application with two routes: "/services", and "/services/:service".

When a user visits the :service state, I'd like him to see a list of information pertaining to one particular service. So far, trivial.

When the same user visits /services, however, I'd like to show a list of services, plus the per-service information (for every service). I'd also like to do this without any template duplication.

The obvious answer seemed to be outlets, however it looks like all outlets have to be statically named, and I have a previously-undetermined number of them. They all have unique names, but of course I can't hardcode the names in the template. I'd like to determine the outlet names dynamically, so I can call this.render appropriately in the renderTemplate to fill them in, but I don't know how to do that.

What would you suggest?

UPDATE: It appears that I can handle my particular case using {{template}}, but that doesn't connect up another route, as such. I'd still like to know how to do that; I'll be doing more complex things later, where that would definitely fit better, and there's still duplication of code in the respective controllers.

UPDATE: I eventually made up my own 'dynOutlet' helper, as such:

// Define "dynamic outlets". These are just like normal outlets,
// except they dereference the outlet name.
Handlebars.registerHelper('dynOutlet', function(property, options) {
  Ember.assert("Syntax: {{dynOutlet <property>}}", arguments.length === 2);
  var context = (options.contexts && options.contexts[0]) || this,
      normalized = Ember.Handlebars.normalizePath(
        context, property, options.data),
      pathRoot = normalized.root,
      path = normalized.path,
      value = (path === 'this') ? pathRoot : Ember.Handlebars.get(
        pathRoot, path, options);
  return Ember.Handlebars.helpers.outlet(value, options);
});

I've yet to figure out if it'll work the way I want, though.

1
Can you knock up a little jsFiddle please?Wildhoney
I'm having trouble making jsfiddle work. Maybe jsfiddle.net/qU44U will give you the idea despite not working, though.Baughn

1 Answers

1
votes

I had also the need to define dynamic Outlets. This is the helper i implemented:

Ember.Handlebars.registerHelper('dynamicOutlet', function(property, options) {
    var outletSource;

    if (property && property.data && property.data.isRenderData) {
      options = property;
      property = 'main';
    }

    outletSource = options.data.view;
    while (!(outletSource.get('template.isTop'))){
      outletSource = outletSource.get('_parentView');
    }

    options.data.view.set('outletSource', outletSource);

    var firstContext = options.contexts.objectAt(0);

    options.hash.currentViewBinding = '_view.outletSource._outlets.' + firstContext.get(property);

    var controller = App.__container__.lookup("controller:movies");
    options.contexts.clear();
    options.contexts.addObject(controller);
    return Ember.Handlebars.helpers.view.call(controller, Ember.Handlebars.OutletView, options);
});

This is the way i use it in my templates:

<div>
  {{title}} <!-- accessing title property of context -->
  {{dynamicOutlet outletName}} <!-- accessing the property that should be used as name of the outlet -->
</div>

The helper makes it possible to use properties of models as outlet names.