// Tutorial //

Handling Events in Polymer

Published on January 20, 2018
    Default avatar
    By Nipuna Gunathilake
    Developer and author at DigitalOcean.
    Handling Events in Polymer

    Events are essential for communicating state in Web Components. In addition to supporting the standard event APIs in modern browsers, Polymer offers simpler ways of event handling. Also, Polymer automatically handles events required for data binding.

    Events in Polymer

    In Polymer, the usual pattern is to pass values down into child components through properties. And to pass changes up to parent components by using events.

    The phrase properties go down, events go up is often used to describe this pattern. Following this pattern makes it possible to handle state changes in a predictable manner.

    Properties go down, events go up

    Mediator pattern

    The mediator pattern is a behavioral pattern where a mediator object handles the communication between its child objects.

    It’s recommended to use this pattern with Polymer Components. One mediator component (e.g.: my-component) handles the communications between its child elements (e.g.: input & h3).

    Annotated Event Listeners

    Annotated event listeners can be used to declaratively create event listeners

    We’ve used this in the article introducing Polymer Properties. We can listen to events on child elements by having a property named on followed by the event name we want to listen to.

    <dom-module id="my-element">
      <template>
        ...
        <div>
          <button type="button" increment on-click="handleIncrement">+</button>
          <span>[[value]]</span>
          <button type="button" decrement on-click="handleDecrement">-</button>
        </div>
      </template>
      <script>
        class MyCounter extends Polymer.Element {
          static get is() { return 'my-counter'; }
          static get properties() {
            return {
              value: {
                type: Number,
                value: 0,
                reflectToAttribute: true,
              },
              increment: {
                type: Number,
                value: 1,
              }
            };
          }
    
          handleIncrement() {
            let incrementedValue = this.value + this.increment;
            this.value = this.isInRange(incrementedValue) ? incrementedValue : this.value;
          }
        }
      </script>
    </dom-module>
    

    In the above example, we call the handleIncrement method when the click event is fired in the button child element.

    Listening to Events

    In Polymer components, how we listen to an event depends on its origin. Events from different origins are handled in the following ways:

    • Custom Elements – Event from the custom element itself. We can add an event listener to the ready function.
    ready() {
      super.ready();
      this.addEventListener('click', this._onClick);
    }
    
    • Child Elements – Event from a child element of the custom element. We can use annotated event listeners as discussed earlier.

    • Outside Elements – Event that’s from outside the scope of the custom element (e.g.: window). For these events, we can add event listeners on connectedCallback.

    constructor() {
      // we need to use handlers bound to the local 'this'
      // to ensure that the 'this' context is properly set
      _boundResizeHandler = resizeHandler.bind(this);
    }
    
    connectedCallback() {
      super.connectedCallback();
      window.addEventListener('resize', this._boundResizeHandler);
    }
    
    disconnectedCallback() {
      super.disconnectedCallback();
      // We must remove listeners to prevent memory leaks.
      window.removeEventListener('resize', this._boundResizeHandler);
    }
    
    _boundResizeHandler
    
    resizeHandler(e) {
      // handle resize event here
      console.log('resized');
    }
    

    Firing Custom Events

    Custom events can be called by creating a new CustomEvent. This is a standard way of creating custom events in modern browsers. Polymer also provides a polyfill for supporting older browsers.

    const event = new CustomEvent('my-event', {bubbles: true, composed: true});
    

    We are setting the following two properties on the CustomEvent:

    • bubbles Allows the event to bubble through the DOM.
    • composed Allows bubbling through Shadow DOMs boundary, setting this to true allows the event to be intercepted by the main DOM.

    Event Re-targeting

    When an event is bubbled up from the inside of the Shadow DOM to its parent, that event becomes re-targeted.

    Meaning that the parent sees the custom element itself as the target of the event. Even when the event is triggered by a child element that’s inside the custom element.

    Composed path for getting event target

    This enables the parent component to handle events without having knowledge of the Shadow DOMs’ structure. But we sometimes do need to find the real target.

    ComposedPath

    If we need to identify the origin of the event, we can use the composedPath property to do so. event.composedPath() returns an array of elements that the event has bubbled through. The very first item in the returned array is the origin element.


    Want to learn more? Join the DigitalOcean Community!

    Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

    Sign up
    About the authors
    Default avatar
    Developer and author at DigitalOcean.

    Still looking for an answer?

    Was this helpful?
    Leave a comment