Index route puzzle


#1

I have created a minimal example of something that puzzles me and was hoping to get some feedback from some Ember mavens about why this happens.

Essentially, it boils down to the Router mapping- adding an empty function or omitting it results in different behavior from Ember and I don’t understand why. Here is the fiddle: http://jsfiddle.net/shhQuiet/fj5MH/5/

Look at App.Router.map and try changing the map statement to the commented one. For completeness, I’ll include the code here:

App = Ember.Application.create({});
App.Router.map(function() {
    // the key difference is here- the empty function
    // is required for the templates to work.
    this.resource('items', function() {}); // this works
//    this.resource('items'); // but this doesn't
});

App.ItemsController = Ember.ArrayController.extend();

App.ItemsIndexRoute = Ember.Route.extend({
  model: function(){
      return [
          {firstName: 'Kris', lastName: 'Selden'},
          {firstName: 'Luke', lastName: 'Melia'},
          {firstName: 'Formerly Alex', lastName: 'Matchneer'}
      ];
  }
});

App.IndexRoute = Ember.Route.extend({
    beforeModel: function() {
        this.transitionTo('items');
    }
});

and the templates:

<script type="text/x-handlebars" data-template-name="application">
    <h1>ember-latest jsfiddle</h1>
    {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="items">
  <h2>Items Content:</h2>
  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="items/index">
  <ul>
  {{#each}}
      <li>{{firstName}} {{lastName}}</li>
  {{/each}}
   </ul>
</script>

#2

For anyone wondering, the defined behavior is specified in the ‘defining your routes’ guide here:

NOTE: If you define a resource using this.resource and do not supply a function, then the implicit resource.index route is not created. In that case, /resource will only use the ResourceRoute, ResourceController, and resource template.

So in this case here, with the empty function Ember is expecting an ItemsIndexRoute and items/index template. But without the empty function that route is not created, only the ItemsRoute and items template are used. I assume this was done for the sake of simplicity. Without the resource function there can be no sub resources, so there is little need to have an extra outlet template layer.


#3

Thanks Eric, that’s a good explanation- I missed that quote from the guide.

We are creating a large application with several developers working on different routes- It has been a common pattern for us to create an index route template along with other sibling routes (edit, etc). But until we are ready to add those routes, we typically just add the empty function so the template location pattern fits all the other resources with other sub-routes. Anyway, makes sense, but Ember could perhaps see the existence of an Index (route/template) and then have the “empty function” behavior.


#4

If you think about it there an index route is hit if you hit nothing deeper in your route than the current resource. There is no real reason for hitting an index route and template if there can be no routing difference between Foo and FooIndex.


#5

This is definitely a gotcha that caught me out when I was starting with ember(been using it very happily for a couple of years now). With a framework that tends to generate anything that you haven’t specified explicitly it’s very surprising to find that you need to add what seems like boilerplate just to nudge ember into creating the index route. It’s little things like this that make ember really hard to get started with, it deviates from the philosophy of the framework. It doesn’t seem like a breaking change, is there any reason to not make generation of the index route a default behaviour?