Search code examples
ember.jsember-dataember-router

Ember Non-Trivial Router With Multiple BelongsTo Relationships


I'm building a project management app with three main models:

Client, Project, Task

My models (relationships only)

let client = DS.Model.extend({
  projects: DS.hasMany('project');
});

let project = DS.Model.extend({
  client: DS.belongsTo('client'),
  tasks: DS.hasMany('task')
});

let task = DS.Model.extend({
  project: DS.belongsTo('project')
});

Requirements:

  1. Display list of all clients
  2. Display list of all a client's projects (not nested in UI)
  3. Display list of a project's tasks (not nested in UI)
  4. Display task's details (not nested in UI)
  5. Display list of all projects for all clients (yep, not nested)

I'm not sure if it's incorrect to reflect model relationships by nesting resources as such:

/** Creates a nested UI by default: */
this.route('clients', function() {
  this.route('projects', function() {
    this.route('tasks', function() {});
  });
});

I don't want my UI to be nested and show all the projects below all the clients etc.


Is there a better way of handling resources than this?

// All projects for all clients
this.route('projects', function(){});

// Client's projects
this.route('clientProjects', { path: 'client/:id/projects' }, function() {});

Solution

  • Nesting routes doesn't necessarily mean that you have to use the nested templates. Each route creates both its route and an index child route. You can see what I mean with this nested list.

    * clients
        * clients.index
        * clients.projects
            * clients.projects.index
            * clients.projects.tasks
                * clients.projects.tasks.index
    

    Note: There is also a much more interactive representation of what I'm talking about at this link.

    If you look at the tree, you can see that clients.index is a sibling to clients.projects. Therefore, if the clients.projects template is showing, it will have replaced clients.index, but still be under clients. The same is true for the clients.projects -> clients.projects.tasks templates.

    This distinction allows you to put whatever you want in each template and have it either retained (nested) or replaced (not). You can fully utilize all of these templates to have some parts nested and some parts not.

    For example, if you put a menu of clients in the clients template, and you put an overview page with statistics about all clients in the clients.index template, when you navigate to the clients.projects template, you will still see the menu with all clients, but the overview template will be replaced.

    Any templates that you don't explicitly create will be created for you with the default {{outlet}} so that they're nestable. Therefore, if you don't create the clients template and put everything in the clients.index template, it will still work, but everything will get replaced when you navigate to the clients.projects template.


    Resources

    Also of note: resource will be deprecated before 2.0, so it's recommended that you just use route everywhere.


    Ember-cli Implementation Commands

    $ ember new myapp && cd myapp
    $ ember g route clients -p
    $ ember g template clients/index -p
    $ ember g route clients/projects -p
    $ ember g template clients/projects/index -p
    $ ember g route clients/projects/tasks -p