Skip to content

Investigating alternate route data patterns #305

@knownasilya

Description

@knownasilya

Managing data in the route has been brought into question a few times, e.g. https://gist.github.com/machty/38bdc3057be92eadbb2e81efc59c4aac, #283

There is also an addon that attempts to accomplish some of the ideas below https://github.com/nickiaconis/ember-prefetch

I'd like to get more people thinking about this, since a gist gets lost pretty quickly.
The goal is to get some concrete ideas that could become an RFC and/or an addon.

What it should do

  1. Only block child routes based on some value, like a blockChildRoutes hook (kind of like beforeModel)
  2. modelFor that returns a promiseproxy (resolved if parent blocked).
  3. model that returns an object and sets it on the controller (new default setupController)
  4. resetController resets the keys set from model on the controller by default
  5. Remove default model behaviour (no auto id lookup via type_key syntax in router definition)
  6. Something else?

Example Code

This code is just an idea to get you thinking.

import Route from 'some-new-route-addon';

export default Route.extend({
  async data({ userId }) {
    // the 'profile' route isn't a parent, so we must pass the arguments
    // so that route gets the right data for us.
    // no arguments and nested means that the existing arguments from the router are used and it might have already been loaded.
    let { profile } = await this.dataFor('profile', { profileId: userId });
    
    return {
      profile,
      user: this.store.findRecord('user', userId)
    };
  }
});

// controller.user === user
// controller.profile === profile

Implementation

Sample implementation on top of existing Route class

import Route from '@ember/routing/route';
import { hash } from 'rsvp';

export default Route.extend({
  model() {
    if (typeof this.data === 'function') {
      let result = this.data.call(this, ...arguments);
    
      return hash(result);
    }
  },
  
  setupController(controller, resolved) {
    if (resolved) {
      let dataKeys = Object.keys(resolved);
      this.dataKeys = dataKeys;
      controller.setProperties(resolved);
    }
  },

  resetController(controller) {
    if (this.dataKeys) {
      let reset = this.dataKeys.reduce((obj, key) => {
        obj[key] = undefined;
        return obj;
      }, {});
      controller.setProperties(reset);
      this.dataKeys = undefined;
    }
  }
});

Relavent code

Docs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions