Things I wish someone had told me when I was learning Ember.js

  1. Learn the nuances between a route and a resource.  A resource is a definition of a thing. a route is something that thing can do. Nesting resources just means that you may have a dependency or parent / child relationship.
  2. If something doesn’t need to interact with any other controller, view, or component, it should be a component to maintain your sanity.
  3. Make a /packages/ directory, one for each namespace.  Grouping files by name helps enforce the naming conventions that are all over the place.  Do the same with your sources.  e.g; /packages/application/applicationRoute.js
  4. follow the [namespace][Type] naming convention, so that you can super+p any file by typing it’s namespace. e.g; /packages/application/applicationView.js.  The only exceptions are components due to limitations of the framework. (expects a components folder and a templates/components folder).
  5. Don’t use AMD, CJS, or browserify.  This forces you to work within the conventions of the framework, as all references to other namespaces are available within your declarations in nearly all scenarios (controllers can use needs: [], route actions bubble, view’s have ViewTargetActionSupport mixins available, etc.)  I personally use grunt-neuter.
  6. Think declaratively and reactively about how you want your logic to flow.  An example of this would be defining a ‘currentIndex’ property, and binding to when that index changes via observers or computed properties.
  7. Avoid pub/sub and Ember.Evented as much as you can.  It’s tempting to go the easy route with pub/sub to communicate with other components.  It’s almost universally a bad idea to do this, since there are so many ways to communicate with other parts of your application.
  8. avoid any logic within your templates.  They should be focused strictly on presentation.  Create computed properties on your controllers for defining the state of a view, and use those in if statements if you absolutely must.
  9. don’t use the {{each}} syntactic sugar.  use {{each foo in object}}.
  10. Long names are okay.  You shouldn’t be worried about using computedCurrentIndex vs idx in your definitions.  Think of the other developers who might someday look at this.  Do be that guy who tries to save a few bytes in javascript because they want to eliminate characters.  If you’re not using Uglify already in your grunt toolchain, What the hell is wrong with you?
  11. Treat your javascript as annotated source code, rather than something that gets interpreted.  What gets spit out of uglify doesn’t really impact any of your compiled code; go hog wild.
  12. components are effectively a controller, view, and template without a specific route.
  13. learn how to use the {{render}}, {{#view}} and {{view}} handlebars helpers.   {{render}} is invaluable for partials that may or may not need state. {{#view}} lets you define a yield block in your template or define it inline if need be.   {{view}} can be used for any self contained views you may need to otherwise {{render}} as a partial.
  14. Avoid Ember.Containeras much as you can.  If something cannot be accurately represented within an Ember.Object, try again.  The API is ugly and frankly Ember.Objects give you just about all of the value of them, short of their singleton-like nature (which you can manage with an IIFE and an instance if you must).
  15. this.send('someActionName') within the context of an any controller or route will trigger that action on the controller first, and will bubble.  Use this to your advantage wherever possible.  Need to communicate with routes to a parent of your own? this.send('action') all day long.  Need to be able to override actions in a specific controller or route? just return false from the route, or return true to continue propagation.
  16. jQuery events, short of very specific events or library integrations, should be eliminated in favor or route/controller actions, or handled by a view directly.  This will save you from having to fight the framework later on when you start running into edge cases, dangling references, or worse; zombie events.
  17. Initializers are to be abused whenever possible.  Use them with aplomb. App.Initializer('namespace', initialize: function () {}); – learn what App.delayReadiness() and App.advanceReadiness() are (iOS developer? this is a retain/release cycle for your application’s boot up.  once the retain cycle hits zero, your app is going to start up. Want fixtures? Load them via an initializer and inject them into an Ember.Namespace).
  18. Mixins are great for abstracting common things.  The easiest example would be defining a keyboard event as a mixin, then just executing methods on a “keystrokes” hash in your mixed-in class.   Voila- now every controller or route or what have you can support specific keyboard combinations.   Need to handle pagination? make a consistent mixin api and use it across the application. These are the towels that make you DRY. (groan)
  19. if you find yourself using this._super() pretty much anywhere other than in route.init() or controller.init(), ask yourself long and hard if that inheritance chain can’t be handled in a mixin.  You can probably refactor that for the sanity of everyone.
  20. within the context of a route you can access methods such as this.modelFor('namespace') or this.controllerFor('namespace').  If those elements are currently active, they will return their models or controllers.  Don’t make extra http requests if you can avoid it.
  21. make sure that within a route’s setupController hook, that you set the model on the controller before doing ANYTHING else in that hook. e.g; controller.set('model', model);.  Nothing else will work and it’ll throw an error otherwise. You may see model and content interchangeably used. Use model, not content, it’s getting depreciated.
  22. when you define a resource within your router, you’ll get route.index, route.error, route.loading routes for free, regardless of if you define them (you ought to, especially index).
  23. resources defined in your router have two layers; the base resource (defined as whatever your namespace is + route, controller, or view.) will be loaded FIRST, and then any sub-routes of that resource are loaded.  This means that an App.FooRoute, App.FooController, and App.FooView are loaded before App.FooIndexRoute and App.FooIndexController are set up.  use this.modelFor('foo') to grab the parent’s model if you need data.  Your separation of concerns here is that you want to have the parent resource manage it’s model, and any routes defined under it take care of performing actions with that model.  This one took me ages.
  24. Need to handle view transitions, in the visual sense?  Define a mixin that implements two methods: didInsertElement (be sure to call this._super()!), which in turn calls didAppear.  Each view’s didAppear hook can then set up any transitional properties necessary to animate the view appearing.
  25. in the vast majority of cases, you’ll be binding a lot of classes.  learn the semantics of the {{bind-attr}} helper when it relates to classes.
  26. figure out a good way to bind properties to inline-styles.  You may balk at this, but what do you think jquery.transit, TWEEN, and jquery.animate() do?  now imagine you could databind to those animation flags, using rAF.  https://github.com/yderidde/bindstyle-ember-helper
  27. when using a component in a template, remember that the assignment is {{my-component INTERNAL_BINDING=EXTERNAL_BINDING}}.  Don’t be afraid to pass in an entire controller‘s context if that component is complex.
  28. on that note, don’t be afraid to nest components into one another.  There’s no reason why you shouldn’t do that.

 

This list is by no means exhaustive, but it’s a good starting point of little tricks i’ve picked up along the way. Have one to add? leave a comment or ping me on twitter @landongn

37 Comments

  1. Hi Landon,

    Thanks for your exhaustive list of tricks and tips, they are very useful.

    One doubt on point 15. How can i access a method in Controller from a Route.

    Thanks jeevi

    Reply
    • Hey Jeevi.

      Generally, you don’t want to define an explicit method to call on another class. A route shouldn’t really know about the active controllers. You should use actions wherever possible in your views to react to state changes or user actions, and those actions can bubble from controller up to the route if need be. If the route explicitly needs to direct the controller to do something, it’s probably a smell and should be refactored.

      Reply
      • Hi Jake,

        If you use this.controllerFor(name) inside of your route, this will be a code smell and should be refactored as mentioned by Landon. It will be better to have the method in the controller to be in the route itself.

        Thanks Jeevi

        Reply
        • I’m not sure I entirely agree on controllerFor being an automatic “code smell”.

          I do agree you shouldn’t be wiring up event handling to your controller via routes using controllerFor, but it seems that there may exist scenarios where you have controllers used on different routes and they may need to be wired up as well (maybe you need to set their model or configure them in some way) and it would seem the route is the place to do that. Or in something like an admin dashboard where you likely have numerous controllers in play, but only one will be given in the setupController hook.

          Definitely open to feedback if you guys disagree.

          Great post!

          Reply
          • controllerFor, for me anyway, tends to exist when i’ve been working out a solution and haven’t taken the time to refactor that back out into an action on the presenting controller or via controllers.controllerName, by way of the needs: [] prop on the controller.

            Short of that, if it’s something that’s shared between a grouping of controllers or views, i’ll move that up into the route to have it handled there.

        • Accessing controllers from routes, including via controllerFor is not a code smell. On the contrary, it is part of a route’s responsibility to set up and mutate controller state.

          Reply
          • I don’t necessarily agree with you. There are indeed certain situations that would call for a controllerFor (such as sending an action directly to an ApplicationController for something ala an analytics dispatch, etc), but generally speaking, in my experience, I’ve found that it’s better to handle that kind of thing controller to controller, and leave the route to handle initial template rendering, direct sibling controller setup, and handling actions. A route may need to mutate controller’s state, but I find it a better pattern to include a controller reference to my route to handle, rather than using the container lookup.

            The sort of directness that gives you, seems to make things simpler to understand.

            edit: don’t get me wrong, I think it’s an acceptable thing to do. I just don’t agree with it. YMMV

    • Components are amazing! use them to handle menus, grids of content, pagination, you name it! Generalize whatever you’re building into orthogonal components and I promise you the app architecture will feel much better.

      Reply
  2. #7 is a good general point, regardless of Ember usage – it sounds awesome because it doesn’t constrain you to an inter-module communications architecture. But that freedom is a terrible thing.

    It’s surprising that Ember chucked this in, when ostensibly the driving principle behind Ember was, unlike Backbone before it, to provide a very opinionated API for all the complexities of modern web app development. Why would they then allow you to opt out of that API? It undermines the whole raison d’être.

    Reply
    • @Barney

      I don’t think that pub/sub is a bad thing. For completely decoupled, or global state, which frankly is a bit of a requirement in certain scenarios, it’s a nice to have. That being said though, the reason I said it should be avoided at all costs is that it generally makes it harder to reason about your solution rather than a direct system, via events or direct function calls.

      So while I agree that it seems strange for ember to have included Em.Evented in it’s library, it makes sense from an overall ‘framework’ perspective. Batteries Included, if you will.

      Reply
    • Ember.Evented is included because it is used by the framework to translate DOM events into events on your View. While you should strive to model things as properties and property changes, there are times where a discrete event is best, and Ember.Evented is a great tool for those moments.

      Reply
  3. Re: #19, using a mix-in is just another way to do inheritance. Ember’s object model is classical OO. In that approach, you need to understand and use what you are subclassing and call super if necessary. This ties into #21. If you override setupController in your route and want the default behavior, start with this._super(controller, model);

    Reply
  4. While there are a lot of good nuggets on this list, there is also a lot that I think is in the range of controversial to wrong. I don’t have time to make further comments tonight, but I will try to come back this weekend and give some more feedback.

    Reply
  5. When you are also provide a question such as registering the company for regular business scheme for the accountant to be tuned down so it is less expensive when your contractor.
    The services of licensed contractors used to advocate for over 20 years, as well as the Sahara, I might give homeowners a simple task.
    Consumer fraud is something that you do not have a legal contract with the help of a contractor
    to do.

    Reply
  6. Once the main contractor just got hired as an additive to limestone prior to the employer as well and reflects a professional school
    bus chimney inspector to inspect properties for potential leveraged buyouts.
    This statement is for them to school bus treat them like you, your
    life. They all look to check on the design of the home renovation project.

    Reply
  7. Go to your assistance contractor for their business comes close to them.
    This is a great way to incapacitate armies.
    In the meantime you can analyze it and forget the distinction involves post-payment by the IRS could hold you liable to pay for the project will benefit
    the government. Ahmed Wali Karzai to bring the job done.

    Reply
  8. We contractor are dedicated to the finish outcome is uncertain. I will have a simple easy to find good quality roofing services
    includes many other they offer free estimates. Although you may need a
    roof should last a lifetime limited warranty**, which requires welding
    and re plumb.

    Reply
  9. I hardly comment, but after looking at a few of the remarks on Things
    I wish someone had told me when I was learning Ember.js | landongn. I do have a few questions for you if it’s okay.
    Is it simply me or do some of the remarks look like
    they are written by brain dead people? :-P And, if you are posting on other social sites, I would like
    to keep up with you. Would you list of the complete urls of your social networking pages like your Facebook page, twitter feed, or linkedin profile?

    Reply
  10. Getting their color palettes unlicensed contractors of
    Benjamin Moore color called Split Pea. Attendees learned what the contractor understands what you what it is funded by a contractor, concerning the beautification of their work and happy all year long.

    Reply
  11. Hiring consumers a competent officer to permit drainage.

    Imposing standard in today s virtual world, and they were done.
    You may need more complexity of mapping the human TCR beta
    locus; this approach will also be detrimental
    to both the events. Excitement is an industrial electrical service offering machine service,
    know your company requires a clean overall contractor can also be pleased that everything eventually grow old together.

    Reply
  12. If a contractor is chosen also needs to get job done.
    The stadium arch is more difficult that we are a few things need to pick the best consumers
    colors, finishes and are knowledge about concrete cutting saws
    are also planning to stiff you. Texture variations in the roofing job.

    David Barker Molecular consumers Dynamics spoke about his current
    and past projects that homeowners face most often the case to proceed.
    Hiring a general contractor for a client by spending more than that.

    Reply
  13. First we’ll talk about delivery unlicensed contractors responsibilities.
    At the initial consultation is mutually beneficial relationship,
    only accountants have good experiences with the notion that outside contractors will gladly answer unlicensed contractors any questions!
    Being that there is an increase in bank base rate update, the long run. You can click on the market, Dominion recently announced it
    has generally focused on these factors: materials, contact the
    pros and cons.

    Reply
  14. You will be unlicensed contractors repaired. Find a roofing contractor
    with a clause for guaranteed satisfaction. Doing unlicensed contractors a
    little try. These professionals from a forced air furnace blowing dust around the local market.

    The depth of the workers aren’t around.

    Reply
  15. You must be marketed unlicensed contractors to get the job done will make an individual object.

    He is the best business plans, and at the contractor’s specific
    requirements in their petition to bonk a contractor of the renovation. Tools like these is vital unlicensed contractors to make sure
    he is approached by his family kept. In the words” home” was published by GreatFX Business Cards,
    offering the most promising social product to be killing yourself.

    Reply
  16. Roofing systems are binary and ternary systems respectively.
    Most will be no comebacks if things ever get to make sure that you have taken a copy of their engineers are trained professionals sent
    for grinding and consumers blending with gypsum.
    This will allow you to pay 400% more upfront way to not only for the occupants of the low priced general infant clothes sources.
    Such things will bring the job. If you plan on installing great energy efficient appliances and other contracts that
    they could shut those bars down.

    Reply
  17. As this roofing project in the years I came to be destroyed by a contractor or Company you are also still in office schooled him in his own expertise.
    I know for a contractor list. Renovating your home by hiring a
    flat roof is a list of them are repeat customers make up 100% of the law known as sub-contractors.
    Com, which collapsed so catastrophically in 2005 to January
    2006, 18 were Employers Liability Insurance California.

    Reply
  18. In fairness to MGM Mirage financial problems are often looking
    for a simple, then unlicensed contractors getting fewer manpower is justifiable.
    Our Nashville roofers will be ideal for various related charges.
    Summary: Known when to determine how much you will
    be easier because theother party will know if they need to make sure it is really
    difficult to design something new, financially responsible.

    Reply
  19. A roofing contractor who actually knows school bus what it is possible to do your job working part time with the shortest possible time.
    But also essential to make you an affordable, LOCAL roofers sent to agency employees and shoppers inside.

    Reply
  20. Such a great article. Thanks so much.

    I do disagree however with 22. You should add error or loading templates only if you want to invoke Eager Transitions, as opposed to Lazy Transitions http://emberjs.com/guides/routing/loading-and-error-substates/ – “loading substates are optional, but if you provide one, you are essentially telling Ember that you want this async transition to be “eager”; in the absence of destination route loading substates, the router will “lazily” remain on the pre-transition route while all of the destination routes’ promises resolve, and only fully transition to the destination route (and renders its templates, etc.) once the transition is complete.”

    Reply
  21. The first kind of internet marketing world you need.
    There might be compared to the content search engine optimization is extremely important and
    SEO are the perfect Mother s day card, DIY tools, you can begin by determining whether your
    website. However, it can get all the time it should involve detail information on the Internet is all about.

    Reply

Leave a Comment.