Computed Properties

Sometimes you may need properties that depend on other properties. For example, you have properties firstName, lastName and also need property fullName that concatenates first and last names. Or you have a boolean property that defines if a button is enabled or disabled, and this property depends on a number of other properties.

Obviously, you shouldn’t manually change a value for such synthetic properties, it should be calculated automatically. Luckily, Polymer provides so called computed properties, and below is an example of using them.

Source code

index.html
<html>
<head>
	<link rel="import" href="src/polymer-advanced/computed-properties/service-agreement.html">
	<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
    <service-agreement></service-agreement>
</body>
</html>
src/polymer-advanced/computed-properties/service-agreement.html
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/polymer/lib/elements/dom-if.html">
<link rel="import" href="../../../bower_components/iron-input/iron-input.html">
<link rel="import" href="../../../bower_components/paper-checkbox/paper-checkbox.html">

<dom-module id="service-agreement">
  <template>

    <template is="dom-if" if="[[!applicationConfirmed]]">
      <div>
        <label>
          Please enter your name and accept our agreement before continuing.
        </label>
      </div>
      <br/>
      <div>
        <iron-input bind-value="{{name}}">
          <input />
        </iron-input>
      </div>
      <br/>
      <div>
        <paper-checkbox checked="{{agreementConfirmed}}">I have read and accepted this agreement</paper-checkbox>
      </div>
      <br/>
      <div>
        <!-- continueEnabled is a computed property -->
        <!--  but it's used as any other property would be used -->
        <button disabled="[[!continueEnabled]]" on-click="continuePurchase">Continue</button>
      </div>
    </template>
    <!-- After a user enters all details and confirms a form we show him this confirmation message -->
    <template is="dom-if" if="[[applicationConfirmed]]">
      <h3>Thank you for your collaboration! We will analyze your application and contact you in 24 hours.</h3>
    </template>

  </template>
  <script>
    class ServiceAgreement extends Polymer.Element {
      static get is() {
        return 'service-agreement';
      }

      static get properties() {
        return {
          name: {
            type: String,
            value: ''
          },
          agreementConfirmed: {
            type: Boolean,
            value: false
          },
          // It's a computed property
          continueEnabled: {
            type: Boolean,
            // In 'computed' property we provide a name of a method to calculate a value
            //  and pass in it all properties this property depends on.
            // The property is re-calculated each time the properties it depends on change.
            computed: 'isContinueEnabled(name, agreementConfirmed)'
          },
          applicationConfirmed: {
            type: Boolean,
            value: false
          }
        }
      }

      isContinueEnabled(name, agreementConfirmed) {
        return name.length > 0 && agreementConfirmed;
      }

      continuePurchase() {
        this.set('applicationConfirmed', true);
      }
    }

    customElements.define(ServiceAgreement.is, ServiceAgreement);
  </script>
</dom-module>

Result

In this example, users cannot submit a form until they type in their name and accept an agreement.

It’s essential to specify what properties we depend on. You cannot just type computed: "isContinueEnabled()" and then use this.name and this.agreementConfirmed in the isContinueEnabled method, because then Polymer won’t know what properties we depend on and it won’t re-calculate a computed property when required.

What we have learned so far
  • We can use computed properties when we need some information that can be calculated based on other properties.