0

I am user iron-list with iron-ajax but after ajax response when pushing element to iron-list giving null exception = "Cannot read property '_list' of undefined"

<script>

    Polymer({
        is: 'my-home',

        ready: function () {
            this.$._ajax.generateRequest();
        },

        onResponse: function (e) {

            var people = e.detail.response.data;
            people.forEach(function (person) {
                this.$._list.push('items', person);
            });
            // Clear the lower threshold so we can load more data when the user scrolls down again.
            this._scrollTheshold.clearTriggers();
        }

    });

</script>

here is my html code of iron-list

 <iron-list id="_list" items="[[data.data]]" as="item">
        <template>

            <div style="margin-top: 0px">

                <!--Card with header image http://placehold.it/350x150/FFC107/000000-->
                <paper-card>

                    <div class="card-content">
                        <h1 class="feed_title">[[item.heading]]</h1>

                        <p class="feed_description">[[item.subheading]]</p>
                    </div>
                    <div class="card-actions">
                        <paper-button class="button-blue">
                            Share
                        </paper-button>
                        <paper-button class="button-blue">
                            Explore
                        </paper-button>
                    </div>
                </paper-card>
            </div>
        </template>
    </iron-list>
user2837615
  • 296
  • 1
  • 5
  • 12
  • I think `this` is not what you think :). Try suggestions from this question: http://stackoverflow.com/questions/346015/javascript-closures-and-this – Tomasz Pluskiewicz Oct 02 '16 at 11:17

2 Answers2

1

In your forEach() function expression, this refers to the Window object, and not the Polymer object. (If using "use strict" here, this would be undefined, but it seems that's not the case for you.)

A few options to fix this:

  • Option 1: Use ES6 arrow function, which does not bind its own this (assuming ES6 is available for you):

    onResponse: function (e) {
      var people = e.detail.response.data;
      people.forEach(person => {
        this.$._list.push('items', person);
      });
      ...
    }
    
  • Option 2: Use ES6 for-of loop, removing need for callback (assuming ES6 is available for you):

    onResponse: function (e) {
      var people = e.detail.response.data;
      for (const person of people) {
        this.$._list.push('items', person);
      });
      ...
    }
    
  • Option 3: Use ES6 spread operator to push all array items at once (assuming ES6 is available for you):

    onResponse: function (e) {
      var people = e.detail.response.data;
      this.$._list.push('items', ...people);
      ...
    }
    
  • Option 4: Pass in a reference to the Polymer object:

    onResponse: function (e) {
      var self = this;
      var people = e.detail.response.data;
      people.forEach(function (person) {
        self.$._list.push('items', person);
      });
      ...
    }
    
  • Option 5: Pass in a reference to the list object:

    onResponse: function (e) {
      var list = this.$._list;
      var people = e.detail.response.data;
      people.forEach(function (person) {
        list.push('items', person);
      });
      ...
    }
    
  • Option 6: Explicitly bind this in your function expression:

    onResponse: function (e) {
      var people = e.detail.response.data;
      people.forEach(function (person) {
        this.$._list.push('items', person);
      }.bind(this));
      ...
    }
    
  • Option 7: Pass this as second parameter of forEach():

    onResponse: function (e) {
      var people = e.detail.response.data;
      people.forEach(function (person) {
        this.$._list.push('items', person);
      }, this);
      ...
    }
    
tony19
  • 125,647
  • 18
  • 229
  • 307
1

Adding to @tony19's answer you can also achieve this with bind

people.forEach(function (person) {
  this.$._list.push('items', person);
}.bind(this));
a1626
  • 2,953
  • 1
  • 19
  • 34