Observers and Computed Properties with Ember.js
Two powerful tools in the Ember.js world are computed properties and observers. If you aren’t familiar with these, don’t worry as examples of both will be given.
Computed Properties
First, let’s look at a computed property
:
This example is a very simple property
. It just takes a model’s firstName
and lastName
and combines them. This property
will be updated any time the model’s firstName
or lastName
changes. This is signified by the collection specified in the property
method (the last line of the sample code). We could then take this property and use it in a template.
Observers
An observer
is very similar to a computed property
, however, it acts more like a method than a property. You wouldn’t use an observer
inside a template. Consider the scenario where you have a “native” fullName
property (not computed like the previous example). You could update the property using an observer
any time the first or last names change. Here’s an example:
Notice the slight differences? Instead of having a return
statement, we simply make a change to our model in the observer
. Also instead of property
, we use the keyword observes
. This is somewhat of a contrived example, as you’d typically just use a computed property like the earlier example, but hopefully you get the idea.
Collections
The previous examples are straightforward and easy to understand, but what if you need to observe something more complicated like a collection? Let’s say you have a model that looks like this (in /app/models/order.js
):
And your LineItem
model looks like this (in /app/models/line-item.js
):
Now let’s assume that we want to know the total of the order. To get this value, we need to monitor each of the line items for price changes. To watch for these changes, we’ll use the @each
property. Here’s what our computed property would look like on our Order
model:
Note there are other ways to accomplish a sum, but for this example hopefully this is easy to understand. The body of the property
isn’t that important. What’s really important in this example is the dependencies that we’re passing to the property
method. We’re saying to Ember, monitor @each
lineItems price
. This will update our total property
any time a price
is modified. You can see why @each
is very powerful.
One More Thing
What if we only want to watch for items being added or removed from the collection? Ember has us covered there as well. Instead of @each
, we can use the []
property instead. Say we wanted just to update our total
only when the collection is altered, here’s what our revised property
would look like:
Of course, this is another contrived example, but it should illustrate the point. It’s also important to note that you shouldn’t end a property/observer with @each
, so no .property('lineItems.@each')
. You must use the []
property instead as shown in the previous example. The usage of ending with an @each
was deprecated in Ember 1.13.x and removed in Ember 2.0, so remember to use the correct syntax!