vendredi 22 juin 2018

Best practice to organize list, view, create and update routes in Ember.js

Working for a few years with ember.js now, it's still not quite clear to me, what should be considered as best practice for structuring list, view, create and update routes.

The projects I've worked with so far mostly used to routing trees per entity. The pluralized entity name for listing with a subroute for create and the singular entity name for detail view with a subroute for editing. As an example a post model would have these for routes: /posts for listing posts, /posts/new for the create functionality, /post/:post_id for showing a single post and /post/:post_id/edit for editing that one. The corresponding router would look like this one:

Router.map(function() {
  this.route('post', { path: '/post/:post_id' }, function() {
    this.route('edit');
  });
  this.route('posts', function() {
    this.route('new');
  });
});

This approach is working quite nicely for detail and edit view cause they are sharing the same model. So the model hook of the edit route could just reuse the model of the detail view route. In ember code this looks like the following:

// app/routes/post.js
import Route from '@ember/routing/route';

export default Route.extend({
  model({ post_id }) {
    return this.get('store').findRecord('post', post_id);
  }
});

// app/routes/post/edit.js
import Route from '@ember/routing/route';

export default Route.extend({
  model() {
    return this.modelFor('post');
  }
});

Normally we would return a collection of posts from posts route model hook and not implementing the model hook of posts.new route (or returning a POJO / Changeset there depending on architecture but that's not the question here). Assuming we are not implementing the model hook of posts.new the routes would look like:

// app/routes/posts.js
import Route from '@ember/routing/route';

export default Route.extend({
  model({ post_id }) {
    return this.get('store').findAll('post');
  }
});

// app/routes/posts/new.js
import Route from '@ember/routing/route';

export default Route.extend({
});

But now this approach is not working well anymore cause a transition to posts.new route is blocked until the collection of posts are loaded. Since we don't need this collection to create a list of posts (at least if we only show them in posts.index route and not on all subroutes) this doesn't feel right.

Side note for those ones not that familiar with ember: Nested routes model hooks are executed in order. So in our case first the model hook of application route, afterwards posts route and then posts.new route waiting for any promise executed by one of them.

So what should then be considered as best practice?

  • Should the fetching of posts live in posts.index route if we are not showing them on nested routes?
  • Shouldn't the create route be a nested under the list route? So should we have posts, post-new, post and post.edit routes? Feels confusing since the post related code is splited over three route trees. Also it would go against the goal of the improved file layout being developed currently since the code would be splitted over three directories.
  • Should we just take the tradeoff of unnecessarily fetching the collection of posts since mostly the user flow comes from this route before the creation route and therefore the model hook is in most cases already loaded anyway?

Would appreciate any thoughts on that one. Decided to not ask that question in the community slack to better document the answer.




Aucun commentaire:

Enregistrer un commentaire