Handling Events in Polymer

While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.

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">
      <button type="button" increment on-click="handleIncrement">+</button>
      <button type="button" decrement on-click="handleDecrement">-</button>
    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;

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() {
  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() {
  window.addEventListener('resize', this._boundResizeHandler);

disconnectedCallback() {
  // We must remove listeners to prevent memory leaks.
  window.removeEventListener('resize', this._boundResizeHandler);


resizeHandler(e) {
  // handle resize event here

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.


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.

Creative Commons License