0

Very similar to How to prevent jquery to override "this" but in ES6.

This is my class:

class FeedbackForm {
  constructor(formEl) {
    this.$form = $(formEl)
    this.$form.submit(this.sendStuff)

    this.alerts = $('#something');
  }

  /**
   * Sends the feedback
   * @param {Event} e
   */
  sendStuff(e) {
    e.preventDefault()

    if (this.alerts.length) {
      window.alert('Notice... stuff')
    }

    $.ajax({
      type: this.$form.prop('method'),
      url: this.$form.prop('action'),
      data: this.$form.serialize()
    }).done(() => window.location.reload(true))
  }
}

The sendStuff method is the event handler of the form, and jQuery calls it using Function.prototype.apply I believe. Therefore, this inside sendStuff is overwritten with the event target that jQuery applies and I can't access this.alerts or any other property methods.

I'm not sure if I can apply the var that = this trick here or how do I work around this issue?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
rink.attendant.6
  • 44,500
  • 61
  • 101
  • 156

3 Answers3

1

You can associate the FeedbackForm instance with the form element using a symbol.

Then, inside the event listener, this or e.currentTarget will be the form element. Using the symbol you retrieve the FeedbackForm instance.

const myFeedbackForm = Symbol();
class FeedbackForm {
  constructor(formEl) {
    formEl[myFeedbackForm] = this;
    this.$form = $(formEl);
    this.$form.submit(this.sendStuff);
    this.alerts = $('#something');
  }
  sendStuff(e) {
    e.preventDefault()
    if (this[myFeedbackForm].alerts.length) {
      window.alert('Notice... stuff')
    }
  }
}
new FeedbackForm(document.forms[0]).$form.submit();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form></form>
<div id="something"></div>

The limitation is that you can't associate the same form element with different FeedbackForm instances.

Oriol
  • 274,082
  • 63
  • 437
  • 513
1

You can use an arrow function:

An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the this value

This should do it:

this.$form.submit(e => this.sendStuff(e));
Johan Karlsson
  • 6,419
  • 1
  • 19
  • 28
0

Try initializing a second sort of storage variable from outside of the scope of both functions inside the main one:

var that;
class FeedbackForm {

  constructor(formEl) {
    this.$form = $(formEl)
    this.alerts = $('#something');
    that = this;

    this.$form.submit(this.sendStuff)    
  }

  /**
   * Sends the feedback
   * @param {Event} e
   */
  sendStuff(e) {
    e.preventDefault()

    if (that.alerts.length) {
      window.alert('Notice... stuff')
    }

    $.ajax({
      type: that.$form.prop('method'),
      url: that.$form.prop('action'),
      data: that.$form.serialize()
    }).done(() => window.location.reload(true))
  }
}
omikes
  • 8,064
  • 8
  • 37
  • 50
  • That crashed Babelify with a syntax error when I tried to transpile as I believe it isn't allowed: "A class body can only contain methods, but not data properties." http://www.2ality.com/2015/02/es6-classes-final.html – rink.attendant.6 Jan 05 '16 at 23:50
  • I have edited my answer. Outside of the class perhaps? Sorry, I guess I am shooting in the dark here. – omikes Jan 05 '16 at 23:52