For below given code this.$.createButton
or document.querySelector('createButton')
works inside the ready
method. But same code fails inside handleRequestSent
or handleResponseReceived
. The error message I get is
Uncaught TypeError: Cannot read property 'createButton' of undefined
I tried to debug, it appears that inside handleRequestSent
and handleResponseReceived
the this
actually pointing to iron-ajax, but not the element dom root. Any suggestion is welcome. Thanks in advance.
<dom-module id="bortini-tv-create">
<template>
<form>
<paper-input label="Name" value="{{tv.name}}"></paper-input>
<paper-input label="Logo" value="{{tv.logo}}"></paper-input>
<paper-input label="Address" value="{{tv.address}}"></paper-input>
<paper-input label="Web site" value="{{tv.webSite}}"></paper-input>
<paper-input label="Registration number" value="{{tv.regNumber}}"></paper-input>
<br/>
<br/>
<paper-button id="createButton" raised on-tap="handleTvCreate">
<iron-icon icon="redeem"></iron-icon>
Add
</paper-button>
<paper-button id="cancelButton" raised on-tap="handleCancelTvCreate">
<iron-icon icon="cancel"></iron-icon>
Cancel
</paper-button>
</form>
<iron-ajax
id="ironAjax"
url="/api/tv"
content-type="application/json"
handle-as="json"
method="POST">
</iron-ajax>
<paper-toast id="toast"
duration="3000"
text="TV {{tv.name}} has been created">
</paper-toast>
</template>
</dom-module>
<script>
function initModel() {
return {"name": "", "logo": "", "address": "", "webSite": "", "regNumber": ""};
}
Polymer({
is: "bortini-tv-create",
properties: {
tv: {
type: Object,
value: initModel(),
notify: true
}
},
ready: function() {
this.$.ironAjax.addEventListener('error', this.handleError);
this.$.ironAjax.addEventListener('request', this.handleRequestSent);
this.$.ironAjax.addEventListener('response', this.handleResponseReceived);
},
handleTvCreate: function (event) {
var ironAjax=document.querySelector("#ironAjax");
ironAjax.body = JSON.stringify(this.tv);
ironAjax.generateRequest();
},
handleCancelTvCreate: function (event) {
MoreRouting.navigateTo('tv-list');
},
handleError: function(event) {
this.$.createButton.disabled=false;
this.$.cancelButton.disabled=false;
var request=event.detail.request;
var error=event.detail.error;
var toast=document.querySelector("#toast");
toast.text="Error: "+error;
toast.show();
},
handleRequestSent: function (request) {
console.log("boooooo");
this.$.createButton.disabled=true;
this.$.cancelButton.disabled=true;
},
handleResponseReceived: function (response) {
document.querySelector('createButton').disabled=false;
document.querySelector('cancelButton').disabled=false;
console.log("Received response: " + JSON.stringify(response.detail.response));
document.querySelector('#toast').show();
MoreRouting.navigateTo('tv-list');
}
});
</script>
Because you set your event handlers imperatively the scope (i.e
this
) the handler is called with, isn't your element instance.Two ways to solve this:
Bind the event handler to your element instance:
this.$.ironAjax.addEventListener('error', this.handleError.bind(this));
This will make sure that
this
inside of the event handler is actually thethis
you want.Define the event handlers declaratively, then Polymer will take care of the proper binding:
<iron-ajax ... on-error="handleError" ...></iron-ajax>
this is because the responseHandler method is fired from an iron-request-element inside. So the this-context moves to the iron-ajax element. If you want to return to your "original" firing element from there, simply use the this.parentElement try something like this:
This should do the trick. Sorry for answering that late. ;)