Accessing DOM Elements

The simplest and the most straightforward method to access an HTML element from JS code is to use id-s. Consider an example below.

Click on the button to see what it’s doing:

Source code

index.html
<html>
<head>
	<link rel="import" href="src/polymer-advanced/dom/colored-square-controller.html">
	<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
    <colored-square-controller></colored-square-controller>
</body>
</html>
src/polymer-advanced/dom/colored-square-controller.html
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="colored-square.html">

<dom-module id="colored-square-controller">
  <template>

    <!-- We provided an id for this element -->
    <colored-square id="square"></colored-square>
    <br/>
    <button on-click="changeColor">Change color</button>

  </template>
  <script>
    class ColoredSquareController extends Polymer.Element {
      static get is() {
        return 'colored-square-controller';
      }

      changeColor() {
        // Accessing an HTML element by id
        this.$.square.changeColor();
      }
    }

    customElements.define(ColoredSquareController.is, ColoredSquareController);
  </script>
</dom-module>
src/polymer-advanced/dom/colored-square.html
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">

<dom-module id="colored-square">
  <template>
    <style>
      .square {
        background: white;
        border: solid 1px black;
        height: 20px;
        width: 20px;
      }

      .square[black] {
        background: black;
        border: solid 1px red;
      }
    </style>

    <!-- black$ instead of black is used in order to make it possible to use this attribute in CSS -->
    <div class="square" black$="[[black]]"></div>

  </template>
  <script>
    class ColoredSquare extends Polymer.Element {
      static get is() {
        return 'colored-square';
      }

      static get properties() {
        return {
          black: {
            type: Boolean,
            value: false
          }
        }
      }

      changeColor() {
        this.black = !this.black;
      }
    }

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

As you can see, Polymer has special shortcut — this.$, which can be used to retrieve an element by its id. In found element, you can change properties and call methods.

Tip

Please note that we used attribute black$ instead of black. What’s the difference?

If we used just black, then during the component initialization Polymer would or would not put black attribute in DOM on div based on if black property is true or false. And if the black property changed later Polymer wouldn’t add/remove this attribute from the div. Therefore, it would be impossible to use this attribute in CSS (.square[black]). But when we use black$, Polymer automatically updates HTML attribute black based on changes in the black property.

That is if in our example we used black instead of black$, then the square would always be white, no matter how much we press the button.

However, the this.$ syntax won’t always work. Let’s put the colored-square component inside an if-template. In this case this.$.square won’t work even if the condition is true. See more in the official guide.

src/polymer-advanced/dom/colored-square-controller-with-if.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="colored-square.html">

<dom-module id="colored-square-controller-with-if">
  <template>

    <template is="dom-if" if="[[someCondition]]">
      <colored-square id="square"></colored-square>
    </template>

    <br/>

    <button on-click="changeColor">Change color</button>

  </template>
  <script>
    class ColoredSquareControllerWithIf extends Polymer.Element {
      static get is() {
        return 'colored-square-controller-with-if';
      }

      static get properties() {
        return {
          someCondition: {
            type: Boolean,
            value: true
          }
        }
      }

      changeColor() {
        // this row is commented because it won't work anyway
        // this.$.square.changeColor();
      }
    }

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

In such cases you can use native DOM API to find a required element: this.shadowRoot.querySelector("selector"). This method will search for the element dynamically.

src/polymer-advanced/dom/colored-square-controller-with-if-fixed.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="colored-square.html">

<dom-module id="colored-square-controller-with-if-fixed">
  <template>

    <template is="dom-if" if="[[someCondition]]">
      <colored-square id="square"></colored-square>
    </template>

    <br/>

    <button on-click="changeColor">Change color</button>

  </template>
  <script>
    class ColoredSquareControllerWithIfFixed extends Polymer.Element {
      static get is() {
        return 'colored-square-controller-with-if-fixed';
      }

      static get properties() {
        return {
          someCondition: {
            type: Boolean,
            value: true
          }
        }
      }

      changeColor() {
        // Dynamically search for the element
        this.shadowRoot.querySelector('#square').changeColor();
      }
    }

    customElements.define(ColoredSquareControllerWithIfFixed.is, ColoredSquareControllerWithIfFixed);
  </script>
</dom-module>
What we have learned so far
  • this.$.{id} can be used to retrieve an element by id. However, it won’t work if this element is added/removed dynamically from DOM.

  • Native DOM API this.shadowRoot.querySelector("{selector}") can be used to find an element by CSS selector.

  • We can change properties on the found element and call its methods.

  • Use special syntax ("black$=") if you want to change attribute (not property). Mostly, it’s required when we want to use these attributes in our CSS.