Templating

Polymer provides convenient means for templating: a conditional template (dom-if) and a template repeater (dom-repeat).

The following example demonstrates these features. It’s a component named name-list, which allows a user to create a list of names. It provides an input where the user can enter some name and confirm it by pushing a confirm button. The confirmed name will be added to the list and displayed below.

To prevent a user from entering too many names there is a property maxNameLength. When a list size reaches some limit (3, by default) the input disappears.

Result

Source code

index.html
<html>
<head>
	<link rel="import" href="src/polymer-basic/templating/name-list.html">
	<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
    <name-list></name-list>
</body>
</html>
src/polymer-basic/templating/name-list.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/polymer/lib/elements/dom-repeat.html">
<link rel="import" href="../../../bower_components/iron-input/iron-input.html">

<dom-module id="name-list">
  <template>

    <!-- dom-if: conditional output. -->
    <!-- Polymer observes changes in the 'addingNameAvailable' property -->
    <!-- specified in the 'if' attribute and shows the element's content depending on it. -->
    <template is="dom-if" if="[[addingNameAvailable]]">
      <iron-input bind-value="{{newName}}">
        <input />
      </iron-input>
      <button on-click="addName">Add name</button>
      <br/>
    </template>

    <!-- dom-repeat: repeated output. -->
    <template is="dom-repeat" items="[[names]]">
      <br/>
      <!-- 'item' is an element of the 'names' array -->
      <div>[[item]]</div>
    </template>

  </template>

  <script>
    class NameList extends Polymer.Element {
      static get is() {
        return 'name-list';
      }

      static get properties() {
        return {
          names: {
            type: Array,
            // Value can be specified not only by literal but also by a function.
            // For properties of type Array or Object it's better to specify a function because
            //  otherwise the value can be shared between different instances of this Polymer element.
            value: function() {
              return [];
            }
          },
          newName: String,
          addingNameAvailable: {
            type: Boolean,
            value: true
          },
          // Nothing prevents us to change this value when we use this web-component.
          // E.g. <name-list max-name-length="5"></name-list> will do the trick.
          maxNameLength: {
            type: Number,
            value: 3
          }
        }
      }

      addName() {
        // We should change properties only by using Polymer mutator methods.
        // If we just use "this.names.push(this.name)" then the component won't be notified s
        // that the property change and UI won't be updated.
        // "push" method is used to add an element to an array.
        this.push('names', this.newName);
        // The same principle applies here.
        // If we just use "this.newName = ''" the component won't know
        //  that something has changed.
        this.set('newName', '');

        if (this.names.length >= this.maxNameLength) {
          this.set('addingNameAvailable', false);
        }
      }
    }

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

This example shows how to work with dom-if and dom-repeat templates.

What we have learned so far
  • dom-if template can be used when some content should be shown/hidden on some condition.

  • dom-repeat template can be used to display an array of elements.

  • The default values of object properties have to be specified with functions to avoid sharing a state between components.