Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using polymer ajax response

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.

like image 231
Ben Thomas Avatar asked Jun 02 '15 08:06

Ben Thomas


2 Answers

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.

like image 54
Joseph Khan Avatar answered Nov 06 '22 17:11

Joseph Khan


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.

like image 33
Ben Thomas Avatar answered Nov 06 '22 18:11

Ben Thomas