0

Can anybody shed a light on why I get the first console message: '1 .list-group-item' on class instantiation, but after button press of '.remove_track', I get this.DOM.TrackItems as undefined? Any help or advice greatly appreciated.

class MyList
        constructor() {
            this.DOM = {
                ParentNode: '#mylist',
                AddTrackButton: '#add_track',
                RemoveTrackButtons: '.remove_track',
                TrackItems: '.list-group-item'
           };

            this.bind(this.DOM.ParentNode, this.DOM.RemoveTrackButtons, 'click', this.removeTrack);

        };

        //jQuery on/off methods
        bind(parentSelector, childSelector, eventName, functionName) {
            console.log('1 ' + this.DOM.TrackItems);
            $(parentSelector).on(eventName, childSelector, functionName);
        };

        unbind(parentSelector, childSelector, eventName, functionName){
            $(parentSelector).off(eventName, childSelector, functionName);
        }

        removeTrack(evt) {
            evt.preventDefault();
            console.log('2 ' + this.DOM.TrackItems);
        }
}

//EDIT:

Here's a jsfiddle

3
  • It works as expected to me. Commented Mar 17, 2018 at 0:27
  • 1
    Please post a Minimal, Complete, and Verifiable example Commented Mar 17, 2018 at 0:28
  • Thanks Ele - jsfiddle included. Commented Mar 17, 2018 at 11:26

1 Answer 1

1

The problem is related to the scope of context this, that approach is using the context of the handler from event click, specifically the clicked button rather than the context of the class MyList.

An alternative is to bind the context using the function bind:

                   +----- This is the object MyList
                   |
                   v
functionName.bind(this); <---- This call returns a new function bound with 
              ^                the specific context.
              |
              +---- This function binds the context

If you need to get access to the clicked element, you can use the param event.

class MyList {
  constructor() {
    this.DOM = {
      ParentNode: '#mylist',
      AddTrackButton: '#add_track',
      RemoveTrackButtons: '.remove_track',
      TrackItems: '.list-group-item',
      Output: '#output'
    }

    this.bind(this.DOM.ParentNode, this.DOM.RemoveTrackButtons, 'click', this.removeTrack);
  };

  bind(parentSelector, childSelector, eventName, functionName) {
    $(this.DOM.Output).html('Called Bind'); //works
    // This is the line with a fix.
    $(parentSelector).on(eventName, childSelector, functionName.bind(this));
  };

  unbind(parentSelector, childSelector, eventName, functionName) {
    $(this.DOM.Output).html('Called Unbind');
    $(parentSelector).off(eventName, childSelector, functionName);
  }

  removeTrack(evt) {
    evt.preventDefault();
    console.log(evt.target);
    console.log(this); // This is just to show the content of this.
    $(this.DOM.Output).html('Called removeTrack');
  }
}

x = new MyList();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="mylist">
  <button class="remove_track">
  HELLO
  </button>
  <div id="output">
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

That's outstanding. Thanks very much Ele.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.