I am trying to fetch the schedule data in JSON format, from the server and use that to render the schdule using a dom-repeat.
The code works fine if I hard-code the JSON, but if I set it using fetch, it does not work.
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="xl-schedule">
<template>
<h1> Excel Schedule </h1>
<template is="dom-repeat" items="{{schedule}}">
<div># <span>{{index}}</span></div>
<div>Event name: <span>{{item.name}}</span></div>
<div>Date: <span>{{item.date}}</span></div>
</template>
<script>
Polymer({
is: 'xl-schedule',
ready: function() {
// this.schedule =
// [
// {
// "name": "Event1",
// "date": "5/10/2016"
// },
// {
// "name": "Event2",
// "date": "5/10/2016"
// },
// {
// "name": "Event3",
// "date": "5/10/2016"
// }
// ];
fetch('resources/schedule.json').
then(function (response) {
return response.json();
}).
then(function (response) {
this.schedule = response;
console.log("response",JSON.stringify(response));
})
.catch(function(err) {
console.log("err",err);
});
}
});
As @Alan pointed out, in your second then
callback:
then(function(response) {
this.schedule = response; // this === window
})
this
does not refer to your Polymer object. The callback is invoked outside your Polymer object's context, where this
is not defined. In non-strict mode, that results in this
defaulting to the global object, which is the window
, so you're actually setting window.schedule
. You can verify that with console.log(this)
in the callback. MDN provides a good reference on this
in regards to function context.
Arrow functions (in ES6) don't have that problem, and this
would be bound to the enclosing context's this
(the Polymer object):
then(response => this.schedule = response) // this === Polymer obj
Assuming you're using ES5 (or prefer not to use an ES6-to-ES5 transpiler), you can set the schedule
property of your Polymer object by passing to your callback a reference to your Polymer object instead of using this
there:
Polymer({
...
ready: function() {
var self = this; // this === Polymer obj
fetch(...)
.then(function(response) {
self.schedule = response;
});
}
});
Note you could prevent this
from defaulting to the global object by declaring "use strict"
. This would cause this
to stay undefined
, which would cause a helpful (fail-fast) error when you accidentally assign to this.schedule
with an unintentional this
:
"use strict";
Polymer({
...
ready: function() {
fetch(...)
.then(function(response) {
this.schedule = response; // TypeError: Cannot set property 'schedule' of undefined
});
}
});
Here's an ES5 demo: plunker