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 onmylistener
event. - Similar to
listen
you can also useunlisten
method remove any listener. - Poperty change fires an event by the name of
property-changed
e.g if property ismyProperty
event will bemy-propert-changed
(camel casing to ’-’). You can listen to them either by usingon-event
attribute oflistener
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.