polymer

Event Handling

Remarks#

  • Here’s a plunker for all the examples
  • Attribute’s name are case-insensitive and will always be converted to lowercase, e.g if you have an attribute on-myListener listener will be set on mylistener event.
  • Similar to listen you can also use unlisten method remove any listener.
  • Poperty change fires an event by the name of property-changed e.g if property is myProperty event will be my-propert-changed(camel casing to ’-’). You can listen to them either by using on-event attribute of listener Object.
  • New value is always stored in e.detail.value for property change events.

Event listening using listener Object

<dom-module id="using-listeners-obj">
  <template>
    <style>
      :host{
        width: 220px;
        height: 100px;
        border: 1px solid black;
        display: block;
      }

      #inner{
        width: calc(100% - 10px);
        height: 50px;
        border: 1px solid blue;
        margin: auto;
        margin-top: 15px;
      }
    </style>
    <div>Tap me for alert message</div>
    <div id="inner">Tap me for different alert</div>
  </template>
</dom-module>
<script>
  Polymer({
    is:'using-listeners-obj',

    //Listener Object
    listeners:{
      //tap a special gesture event in Polymer. Its like click event the main difference being it is more mobile deivce friendly
      'tap':'tapped',  //this will get executed on host of the element
      'inner.tap':'divTapped' //this tap will get executed only on the mentioned node (inner in this case)
    },

    tapped:function(){
      alert('you have tapped host element');
    },

    divTapped:function(e){
      event.stopPropagation();  //this is only to stop bubbling of event. If you comment this then tap event will bubble and parent's(host) listener will also get executed.
      console.log(e);
      alert('you have tapped inner div');
    }
  })
</script>

Annotated Listener

Another way to add an event listener is to use on-event annotation in DOM. Below is an example using up event, which is fired when finger/mouse goes up

<dom-module id="annotated-listener">
  <template>
    <style>
      .inner{
        width: calc(200px);
        height: 50px;
        border: 1px solid blue;
        margin-top: 15px;
      }
    </style>
    <!-- As up is the name of the event annotation will be on-up -->
    <div class="inner" on-up='upEventOccurs'>Tap me for different alert</div>
  </template>
</dom-module>
<script>
  Polymer({
    is:'annotated-listener',
    upEventOccurs:function(e){
      //detail Object in event contains x and y co-ordinate of event
      alert('up event occurs at x:'+e.detail.x+' y:'+e.detail.y);
    }
  })
</script>

Imperative listener

You can also add/remove listener imperatively using listen and unlisten method of Polymer

    <dom-module id="imparative-listener">
      <template>
        <style>
          #inner{
            width: 200px;
            height: 50px;
            border: 1px solid blue;
            margin-top: 15px;
          }
        </style>
        <div id="inner">I've imparative listener attached</div>
      </template>
    </dom-module>
    <script>
      Polymer({
        is:'imparative-listener',
        
        //keeping it in attached to make sure elements with their own shadow root are attached
        attached:function(){
          this.listen(this.$.inner,'track','trackDetails'); // For more details on method check https://www.polymer-project.org/1.0/docs/api/Polymer.Base#method-listen
        },
        
        //all the listener functions have event as first parameter and detail (event.detail) as second parameter to the function
        trackDetails:function(e,detail){
          if(detail.state=='end'){
            alert('Track distance x:'+detail.dx+' y:'+detail.dy);// For more details on track event check https://www.polymer-project.org/1.0/docs/devguide/gesture-events
      }
    }
  })
</script>

Custom Events

You can also fire your own events and then listen to them from either Polymer element of HTML page

This Element fires the custom event

    <dom-module id="custom-event">
  <template>
    <style>
      #inner{
        width: 200px;
        height: 50px;
        border: 1px solid blue;
        margin-top: 15px;
      }
    </style>
    <div id="inner" on-tap="firing">I'll fire a custom event</div>
  </template>
</dom-module>
<script>
  Polymer({
    is:'custom-event',
    firing:function(){
      this.fire('my-event',{value:"Yeah! i'm being listened"}) //fire is the method which is use to fire custom events, second parameter can also be null if no data is required
    }
  })
</script>

Here’s an element which is listening to that custom event

  <link rel="import" href="custom-event.html">
 <dom-module id="custom-event-listener">
  <template>
    <style></style>
    <custom-event on-my-event="_myListen"></custom-event>
  </template>
</dom-module>
<script>
  Polymer({
    is:'custom-event-listener',
/*    listeners:{ //you can also use listener object instead of on-event attribute
      'my-event':'listen'
    },*/
    _myListen:function(e,detail){
      alert(detail.value+"from Polymer Element");
    },
  })
</script>

Listening from HTML

<html>
  <head>
    <meta charset="UTF-8">
    <title>Events</title>
    <script src='bower_components/webcomponentsjs/webcomponents-lite.min.js'></script>
    <link rel="import" href="./bower_components/polymer/polymer.html">
    <link rel="import" href="custom-event-listener.html">
  </head>
  <body>
    <!--As event bubbles by default we can also listen to event from custom-event-listener instead of custom-event-->
    <custom-event-listener></custom-event-listener>
  </body>
  <script>
    document.querySelector('custom-event-listener').addEventListener('my-event',function(e){
      console.log(e);
      alert(e.detail.value+"from HTML");
    })
  </script>
</html>

Property change event

Properties with notify:true also fires an event

<link rel="import" href="../bower_components/paper-input/paper-input.html">
<dom-module id="property-change-event">
  <template>
    <style></style>
    <paper-input id="input" label="type here to fire value change event" on-value-changed='changeFired'></paper-input>
  </template>
</dom-module>
<script>
  Polymer({
    is:'property-change-event',
    changeFired:function(e){
      if(e.detail.value!="")
        alert("new value is: "+e.detail.value);
    }
  })
</script>

Event Retargeting

It is possible to retarget an event in Polymer ie you can change event details like path thus hiding the actual details of an event/element from user.

For e.g if a div inside event-retargeting element is firing the event but developer does not want the user to know that he can retarget the event to event-retargeting element by using the following code.

var targetEl = document.querySelector('event-retargeting');
var normalizedEvent = Polymer.dom(event);
normalizedEvent.rootTarget = targetEl;
normalizedEvent.localTarget =targetEl
normalizedEvent.path = [];
normalizedEvent.path.push(targetEl);
normalizedEvent.path.push(document.querySelector('body'));
normalizedEvent.path.push(document.querySelector('html')); 

To see the working example please refer to plunker in remarks section.


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow