Private Methods and Properties

Any Polymer component can expose an API consisting of a number of methods and properties. These component members can be called public. But there are also properties and methods that are supposed to be used only by the component itself. We can call these members private.

It’s a good practice to prefix private methods and properties with underscore.

See an example below.

Disco lights application

Source code

index.html
<html>
<head>
	<link rel="import" href="src/recipes/convention/access-control/disc-jockey.html">
	<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
    <disc-jockey></disc-jockey>
</body>
</html>
src/recipes/convention/access-control/disc-jockey.html
<link rel="import" href="../../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="disco-lights.html">

<dom-module id="disc-jockey">
  <template>

    <disco-lights id="square"></disco-lights>

    <br/>
    <br/>

    <button on-click="_start">Start</button>
    <button on-click="_stop">Stop</button>

  </template>
  <script>
    class DiscJockey extends Polymer.Element {
      static get is() {
        return 'disc-jockey';
      }

      _start() {
        this.$.square.start();
      }

      _stop() {
        this.$.square.stop();
      }

    }

    customElements.define(DiscJockey.is, DiscJockey);
  </script>
</dom-module>
src/recipes/convention/access-control/disco-lights.html
<link rel="import" href="../../../../bower_components/polymer/polymer-element.html">

<dom-module id="disco-lights">
  <template>
    <style>
      .square {
        background: black;
        display: inline-block;
        height: 20px;
        width: 20px;
      }
    </style>

    <div class="square" id="square"></div>

    Current color: [[_currentColor]]

  </template>
  <script>
    class DiscoLights extends Polymer.Element {
      static get is() {
        return 'disco-lights';
      }

      static get properties() {
        return {
          // 'colorChangeInterval' is a public property because
          //  it's very possible that a client of the component might want
          //  to change it
          colorChangeInterval: {
            type: Number,
            value: 800
          },
          // Scheduler id is used for some internal work.
          // Therefore, it's a private member.
          _schedulerId: {
            type: Number,
            value: null
          },
          // The current color is displayed in the UI of this component.
          _currentColor: String
        }
      }

      // It's definitely a public method because it's intended
      //  to be used by some outer component
      start() {
        if (!this._schedulerId) {
          this._startChangingColor();
        }
      }

      stop() {
        if (!!this._schedulerId) {
          clearInterval(this._schedulerId);
          this.set('_schedulerId', null);
        }
      }

      // It's not a public member but we have no means to change a name
      //  of a standard lifecycle callback method
      connectedCallback() {
        super.connectedCallback();
        this._startChangingColor();
      }

      // The method is supposed to be used only by the component itself.
      // So, it's a private member.
      _startChangingColor() {
        const schedulerId = setInterval(function() {
          let color = '#';
          for (let i = 0; i < 6; i++) {
            color += '0123456789ABCDEF'[Math.floor(Math.random() * 16)];
          }
          this.$.square.style.backgroundColor = color;
          this.set('_currentColor', color);
        }.bind(this), this.colorChangeInterval);

        this.set('_schedulerId', schedulerId);

      }
    }

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

The _currentColor property is made private, but for a component which is designed to be reusable across many projects this property could be public. Another option would be creating an event with the information about currently selected color.

By adopting this convention we achieve at least the following goals:

  • We explicitly declare what element members can be used.

  • We make an API more clear and obvious.

  • During refactoring, we clearly see names of properties and methods that shouldn’t be changed.