0

I have this es6 class:

class CommentsController {
  constructor() {
    this.$addCommentForm = $('.add-comment')
    this.$addCommentButton = $('.add-comment input[type=submit]')
  }

  init() {
    this.addCommentFormListener();
  }

  addCommentFormListener() {
    this.$addCommentButton.on('click', function(e) {
      e.preventDefault();

      let imageId = parseInt($(this).parents('ul').data('id'));
      let inputText = $(this).parents('ul').find('.user-text').val();
      let comment = new Comment(inputText, imageId);
      debugger;
      CommentsController.renderComment(comment, imageId)
    });
  }

  renderComment(comment, imageId) {
    let image = Image.all[imageId]
    image.comments.push(comment)
    $('#images').find(`ul[data-id=${imageId}] ul#comments-${imageId}`).append(`<li>${comment.text}</li>\n`);
  }
}

The problem is that at the debugger, I want to call the renderComment function but I cannot because this does not refer to the controller anymore. What can I do?

Jwan622
  • 11,015
  • 21
  • 88
  • 181
  • Of course, `renderComment` doesn't use `this` at all, so it doesn't really matter. You could just make it a `static` method (that's how you are calling it anyway - on the `CommentsController` class, not an instance) and it would work. – Bergi Oct 31 '17 at 22:33

1 Answers1

1

Use an arrow function instead of a function:

An arrow function does not have its own this; the this value of the enclosing execution context is used.

However, now you can get the clicked element from this, because this refers to the instance. Instead get the clicked element using Event.target:

  addCommentFormListener() {
    this.$addCommentButton.on('click', (e) => {
      e.preventDefault();

      const $el = $(e.target);
      const imageId = parseInt($el.parents('ul').data('id'));
      constinputText = $el.parents('ul').find('.user-text').val();
      const comment = new Comment(inputText, imageId);

      this.renderComment(comment, imageId)
    });
  }
Ori Drori
  • 183,571
  • 29
  • 224
  • 209