Understanding Ember.js Computed Properties

Ember has a lot of great things going for it. One of the Ember features I constantly praise is computed properties. The Ember guides are a great starting point to learn about computed properties. Computed properties allow quick ways to massage and manipulate data into the form your application needs it. It makes presenting data a cinch.

What is a computed property?

Per the Ember docs:

In a nutshell, computed properties let you declare functions as properties. You create one by defining a computed property as a function, which Ember will automatically call when you ask for the property. You can then use it the same way you would any normal, static property.

In practice a computed property may look like this:

fullName: (->
  @get("firstName") + " " + @get("lastName")
).property("firstName", "lastName")

Why are computed properties helpful?

Computed properties make it easy to transform values into new ones. For example, let’s say we have a property monthId that uses the convention YYYYMM. We use the monthId to determine what data we show. However, in our UI we want to show the month in a more human readable form. We can use a computed property to do this!

monthDescription: (->
  # Use moment to sanely parse a date
  date = moment(@get("monthId"), "YYYYMM")
  # Return a string format of the date, ex: 12/2015
  date.format("MM/YYYY")
).property("monthId")

Shorthand Properties

Often times you’ll want to use a computed property to transform an array. Check out the Ember API for a comprehensive list (methods start with computed). Essentially, Ember exposes several convenience methods to help generate computed properties from sorting, filtering, or joining data.

For example, if we have a number of attendees that we want to display in alphabetical order it is as simple as:

  attendeeSortOption: ['lastName']
  attendeesByName: Em.computed.sort("attendees", "attendeeSortOption")

The attendeeSortOption property defines how to sort the attendees. If this property changes, the attendeesByName property will automatically be re-computed.

Computed Properties from Arrays

In certain cases, you may want to create a computed property from an array that doesn’t fit into any off-the-shelf function. There are multiple ways a computed property can depend on an array. Let’s use the same attendee example from above to illustrate these ways.

  1. "attendees"
  2.   theProp: (->
        # Do some computed property things
      ).property("attendees")

    When you depend on the array by name, the computed property will only be recalculated when the attendees is set to a new array.

  3. "attendees.@each.lastName"
  4.   theProp: (->
        # Do some computed property things
      ).property("attendees.@each.lastName")

    When you use the @each keyword, the computed property will be recalculated if any of the lastName properties change in the array, or if an item is added or removed from the array, or if the array is set to a new instance.

  5. "attendees.[]"
  6.   theProp: (->
        # Do some computed property things
      ).property("attendees.[]")

    The [] syntax will be recomputed for the exact same reasons as the @each syntax, except that the [] should be used when the elements in the array are not Ember objects.

Computed Properties vs. Observers

One common point of confusion in Ember is when to use computed properties and when to use observers. Computed properties should be used for any property that will be consumed in the view template. You will get an error if you try to use an observer in the template because the observer returns the declared function, not the value from the function.

What other things do you find helpful about Ember computed properties? What frustrates you? Please comment below.