Reputation: 3200
I have the following polymer element which I have created:
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="task-list-app">
<style>
:host {
}
</style>
<template>
<iron-ajax auto url="../tasks.json" handle-as="json" on-response="handleResponse"></iron-ajax>
<template is="dom-repeater" items="{{todos}}">
<span>hello</span>
</template>
</template>
</dom-module>
<script>
Polymer({
is: "task-list-app",
created: function () {
this.todos = [];
},
handleResponse: function (data) {
this.todos = data.detail.response;
}
});
</script>
I am calling this inside my index.html by doing:
<task-list-app></task-list-app>
I am expecting that for every object returned in the todo array, a <span>
will be printed. However, when I run the app, I get the following output in the console:
Uncaught TypeError: Cannot read property 'todos' of undefined
in polymer.html line 1001
I am not sure what is happening here and how to reference the data received back from the ajax response.
Upvotes: 6
Views: 23456
Reputation: 133
You need to define property before using it in scripts:
<script>
Polymer({
is: "task-list-app",
properties: {
todos: {
type: Array,
notify: true
}
},
handleResponse: function (data) {
this.todos = data.detail.response;
}
});
</script>
Upvotes: 5
Reputation: 3200
After banging my head on the wall for a few hours I have managed to solve this. I have created my own element called ajax-service
that has a public property called todos
which is an Array
. In this element, I use the iron-ajax
element to do the ajax call.
When the ajax is complete, a function is called and the response is set on the todos
property. I have also set the keys reflectToAttribute
and notify
to true. This means the todos
property's value is reflected back to the attribute on the host node and that it is available for two-way binding (see here for more information).
My task-list-app
element is as follows:
<link rel="import" href="ajax-service.html">
<link rel="import" href="task-item.html">
<link rel="import" href="tiny-badge.html">
<dom-module id="task-list-app">
<style>
:host {
}
</style>
<template>
<ajax-service todos="{{todos}}"></ajax-service>
<template is="dom-repeat" items="{{todos}}">
<task-item task="{{item}}"></task-item>
</template>
<div>
<tiny-badge>[[todos.length]]</tiny-badge> total tasks
</div>
</template>
</dom-module>
<script>
Polymer({
is: "task-list-app"
});
</script>
and my ajax-service
element:
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="ajax-service">
<style>
:host {
}
</style>
<template>
<iron-ajax auto url="../tasks.json" handle-as="json" on-response="tasksLoaded"></iron-ajax>
</template>
</dom-module>
<script>
Polymer({
is: "ajax-service",
properties: {
todos: {
type: Array,
reflectToAttribute: true,
notify: true
}
},
attached: function () {
this.todos = [];
},
tasksLoaded: function (data) {
this.todos = data.detail.response;
}
});
</script>
Doing it this way means I am able to edit the data in the on-response
function before setting it on the element.
Upvotes: 6
Reputation: 442
First of all second template that you are using to loop through your data should be a "dom-repeat" and not a "dom-repeater". Secondly you can directly bind the response of iron-ajax to your looping template. Like this,
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="task-list-app">
<style>
:host {
}
</style>
<template>
<iron-ajax auto url="../tasks.json" handle-as="json" last-response="{{ajaxResponse}}"></iron-ajax>
<template is="dom-repeat" items="[[ajaxResponse.todos]]">
<span>{{item.todoItem}}</span>
</template>
</template>
</dom-module>
<script>
Polymer({
is: "task-list-app"
});
</script>
So you are basically binding value of last-response property to your looping template directly.
Upvotes: 12