37
votes

I have read most of the beginner guides on the Ember.js site but I am still confused about the correct place to put stuff.

  1. Route - from online research people suggested putting routing related logic in the route. That is all good, but the only thing I can think of is this.transisionTo(). I read somewhere else that all model related operations should be in the route because that is where the model field is defined. Is this correct? What are some good use cases of putting actions in the route over the controller?

  2. View - Currently, I can't see the point of the view. The docs say that it handles native DOM events but I will probably always use the {{action}} helper which will be handled by the controller. So what are some good use cases of using the view over the controller in regards to actions? What are some good use cases of the view generally considering I will be using components over views for reusable code.

  3. Controller - It appears to me that the controller can do anything the View or Route can do. It can transition using this.transitionToRoute(), it can save models using this.get('model').save() and can handle actions using the {{action}} helper. All the beginner tutorials seem to ignore the view altogether and use the controller instead. What are some good use cases of using the Controller over the View or Route?

I guess this all comes down to poor understanding of how everything hangs together. I can't find anything online or in the docs that is explicit about the grey areas such as where to use the {{action}} helper for different scenarios. Links to some good materials would be helpful too.

2
actions can be pointed at a view... What if you want to turn a div green three seconds after it renders? Controller can't help you there. :) The view, however, has a handy-dandy hook for such a scenario. Go look at all the available view hooks and methods and the utility of views will be obvious.Matthew Blancarte
@Matthew Can't I just have have a timer on the controller Ember.run.later(function(){ self.set('isGreen', true);}, 3000); where isGreen is bound to the div class. <div {{bind-attr class="isGreen:green"}}jax
Sure but that would be like using a saw handle to hammer in a nail. Wrong use of tools. {{bind-attr}} is meant to bind model and computed properties, not create a visual effect 3 seconds after rendering. You would want to put that Ember.run.later into the didInsertElement of the view.Matthew Blancarte
@Matthews, this is my point. For a beginner, it is not clear where operations should be done. To you it might be obvious that you would not do it from the controller but for a beginner it seems perfectly acceptable. There needs to be some sort of flowchart or something to help you decide where your logic should go.jax

2 Answers

17
votes

Update: Not all of this information will be correct for Ember 2. As far as I know Ember 2.0 will only use Components.

How Various Components of Ember.js Fit Together

Model

A Model takes care of interacting with a data store. An example of data store can be a RESTful server or Localstorage.

Template

A Template takes care of building HTML from data available to its Controller and View. A Controller in turn has access to a Model.

Controller and View

Controllers and Views are very similar and both act on user generated events. A Controller is supposed to take action on semantic events like submit and a View is supposed to take action on interaction events like focus or click.

Router

Ember has a single Router. Router links urls to Routes. For example users/:user_id to users.show route or UsersShowRoute.

Route

Each Route, when activated, takes care of unpacking a url to an state. For example users/:user_id requires a user to be logged in in order to see a friends profile. A Route makes sure a user is logged in and takes care of state of being logged in.

A Route fetches information from data store. For example users/pekhee will fetch pekhee user from a data store and give it to Controller and View.

A Route dynamically chooses what Controller and View it needs or how many of them it needs.

A Route manages state of an application and how that state should be represented. However Models take care of managing state of application for Route and Controllers/Views take care of managing nitty gritty details of its representation.

Keep Logic as Relevant and as Local as Possible: Some Notes

  • If your logic doesn't care about any context or model put it in activate callback of route.
  • If a piece of logic only needs to know model put it in afterModel callback of route.
  • If it needs to know context of Controller or interact with semantic meaning of a resource put it in a controller.
  • If it needs to know context of View or interact with representation of a resource put it in a view.
  • If it needs to know both contexts or interact with both semantic and presentation of a resource first give the event to a view then escalate it to a controller.

Examples

When more than one Controllers work with one Model, keep semantic actions on highest possible Route in the chain otherwise keep logic in most local Controller.

Keep animation related code in View and use Liquid Fire.

Sometimes each user has a lot of posts and each post has a lot of comments. Try to have a Route return relevant user. Then ask relevant user for posts in PostsRoute and after that try to ask for relevant comments in CommentsRoute. This keeps logic as local as possible. You comments route doesn't need to know how you retrieve a user.

0
votes

I think ember2.0 meant to abandon view and controllers, it wants to make your codes more reusable and that's why components are more welcome. For the benefit of putting actions in route instead of controllers, I can only see that it ease the understanding of ember for new users. You can't need to spend a massive time on trying to understand the relationship between controller, route, router, view and template anymore. That's my guess though.