Series: Computed Properties

Intro to Computed Properties

Published on Jul 25, 2015

Computed properties are a huge part of why transforming and creatively displaying data in Ember is such a joy.

In this episode we go over the basics of how computed properties work (using the canonical use case as our example) and discuss some common pitfalls.


Links

Code

//demonstrations/computed-getter/controller.js
import Ember from 'ember';

export default Ember.Controller.extend({
  firstName: 'Tony',
  lastName: 'Stark',
  fullName: Ember.computed('firstName', 'lastName', function(){
    return `${this.get('firstName')} ${this.get('lastName')}`;
  }),
  companyName: 'Stark Industries',
  businessCard: Ember.computed('fullName', 'companyName', function(){
    return `${this.get('fullName')} of ${this.get('companyName')}`
  })
});
//demonstrations/computed-getter/template.hbs
First name: {{input type='text' value=firstName}}<br>
Last name: {{input type='text' value=lastName}}<br>
Full name: {{fullName}}<br>
Company: {{input type='text' value=companyName}}<br>
Business Card: {{businessCard}}

Transcript

Computed properties are an important part of everyday Ember programming. In this episode, we’ll go over the basics, showing what they are, how to use them, as well as a few subtleties that you might not know even if you’ve been programming Ember a while.

This is the canonical computed properties example. It’s like the hello world of computed properties. Here we have two different properties, firstName and lastName, and then we’re going to combine them to get a fullName. So you have the firstName then a space and the lastName. And then you use that property just like you would any other property. So here in the template we’re going to display it, and it combines them.

One of the great things about computed properties is that they’re bound to the properties that are computing them. So if we change one of those properties that it’s computed on, the computed property will change. Let me show you what I mean. So here if we change the first name, then it changes the full name. It updates automatically. Let’s deconstruct how the computed property knows how to update.

So here when we’re declaring it, we declare firstName and lastName and then the function. So if we take away firstName here, then it won’t be able to recognize when the firstName is updated anymore. Here’s a demonstration. It’s not updating anymore because we haven’t declared that it depends on firstName. If we add the firstName back to its dependencies, then it’ll update.

So the form of the Ember.computed helper is a list of dependencies. It can be any length. It can even be a length of zero, in which case it just gets computed once and stays like that for the length of the program, or it can be one, two, five, two hundred.... please don’t make it two hundred, and then a function.

So as we said, computed property is a property. That means it can be used in other computed properties. Here we’ve added companyName and businessCard. businessCard depends on fullName and the companyName. It’s treating fullName and companyName the same because they are both properties, even though one is computed. So let’s go ahead, add those to our template, and see it in action. Here we can change the first name. It’ll propagate to the full name, and then that will propagate to the business card. And we can change the company name and that will just propagate to the business card.

One of the huge advantages performance-wise of using computed properties is that they’re cached. Let me show you what I mean. We’re going to log out whenever we’re computing the fullName and whenever we’re computing the businessCard. So in the initial computation, it computes the fullName then it computes the businessCard. Then when we change the firstName, every time we type a letter it computes the fullName and it computes the businessCard. However when we change the company, it’s only computing the businessCard. That’s because neither of the properties that are feeding into the fullName are changing. So even though we’re calling the full name and we’re calling the company in order to compute the business card, only company is changing, and so fullName doesn’t get recomputed.

If we were using functions instead of properties, then we would be calling fullName every time. The performance difference between functions and computed properties gets huge when you have a lot of objects that depend on each other and when you have a large dependency tree. So if only one branch is changing, you don’t need to recompute the whole tree.

One other important thing to note is that if the computed property is never requested from somewhere, then it will never be computed. So let’s take away the businessCard on the template. And then when we reload, we’ll see that it never computes the business card. However, it’s not just templates that can request a computed property. We will add back in the businessCard then take away the fullName, and we’ll see that fullName is still computed, although the ordering we can see is a bit different. It computes businessCard first, then because it needs fullName for businessCard, it computes fullName. And because of this irregularity in when it gets called, as well as the fact that it’s a property not a method, you should never have side effects on your computed properties. I’ll repeat that, never have side effects on your computed properties.

So in this episode, we learned the basics of computed properties, how to use them in their most common form, as well as some common pitfalls to avoid. In this week’s pro-episode, I’ll show you how to use computed properties with lists using some special syntax. And then next week we’ll be back with even more advanced stuff using computed properties. I’ll see you then.

Computed Properties

Subscribe to our mailing list