Polymer this.push not working

In Polymer 1.x I am trying to push data from my database to an array, but for whatever reason, it suddenly stopped working.

When running this code

ready: function(){
    var leserbriefRef = firebase.database().ref('leserbriefe');
        leserbriefRef.on('value', function(snap) {
          var n = snap.child('numLeserbriefe').val();
          console.log(n);
          this.lbriefe = [];
          for(var i=0; i<n; i++){
                this.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
            }
        });
  }

I get this error message: firebase.js:283 Uncaught TypeError: this.push is not a function

I don't know why. Earlier this week it still worked.

Answers:

Answer

This is a common gotcha among js beginners, basically the usage of the this keyword. The context of the this variable inside the anonymous function is not the one you intended (in this case, the element). To solve this, you can use closures[1], .bind[2], or the newer ES2015 arrow functions[3].

Closure

ready: function() {
  // assign this to self
  var self = this;

  var leserbriefRef = firebase.database().ref('leserbriefe');
  leserbriefRef.on('value', function(snap) {
    var n = snap.child('numLeserbriefe').val();
    console.log(n);
    self.lbriefe = [];
    for(var i = 0; i < n; i++){
      self.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
    }
  });
}

.bind

ready: function() {
  var leserbriefRef = firebase.database().ref('leserbriefe');
  leserbriefRef.on('value', function(snap) {
    var n = snap.child('numLeserbriefe').val();
    console.log(n);
    this.lbriefe = [];
    for(var i = 0; i < n; i++){
      this.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
    }
  }.bind(this)); // bind this keyword to element's
}

ES2015 arrow function (might as well go full ES2015)

ready() {
  const leserbriefRef = firebase.database().ref('leserbriefe');
  leserbriefRef.on('value', (snap) => { // arrow functions!
    const n = snap.child('numLeserbriefe').val();
    console.log(n);
    this.lbriefe = [];
    for(let i = 0; i < n; i++){
      this.push("lbriefe", snap.child(`l${n - 1 - i}`).val());
    }
  });
}

Sources:

[1] https://developer.mozilla.org/en/docs/Web/JavaScript/Closures

[2] https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

[3] https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Answer

well you have to watch for this binding, since the scope of this is changes inside functions.

ready: function(){
    var leserbriefRef = firebase.database().ref('leserbriefe');
        leserbriefRef.on('value', function(snap) {
          var n = snap.child('numLeserbriefe').val();
          console.log(n);
          this.lbriefe = [];
          for(var i=0; i<n; i++){
                this.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
            }
        }.bind(this));
  }

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.