0

I have a multistep form, with 4 frameset. Each one must come in when I press the "Next" button (of course)

My ES6 modular code cointains something like this:

class FormController {
  // 1. describe and initiate object
  constructor() {
    this.nextBtn = $(".next");
    this.next_fs;
    .... 

    this.events();
  }

  // EVENTS LISTENER
  events(){
    this.nextBtn.on("click", this.nextClicked.bind(this));
    // other listeners
  }

  nextClicked() {
    this.next_fs = $(this)
      .parent()
      .next(); // this is the next fieldset
    // some actions...
  }
// rest of the code
}

My problem is the following: I need to bind "this" inside nextClicked function to be able tu use all variables and methods like this.next_fs, this.saveData(), etc...

But I also need to know which button has been clicked, and I cannot know that because this is no more "this button", and I cannot pass a variable (let's call it 'e') to trace the e.target.

What's the matter with my code? I know that's something stupid that I'm not seeing.

Thanks!

Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
Simone Conti
  • 349
  • 1
  • 17
  • Does this answer your question? [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Tschallacka Feb 03 '20 at 16:03
  • Well... partially. Following that, I have to use a self variabile to store a "this" reference in the constructor. I'll try, but I believe there's a smarter solution somewhere.... – Simone Conti Feb 03 '20 at 16:08

3 Answers3

2

But I also need to know which button has been clicked, and I cannot know that because "this" is no more "this button", and I cannot pass a variable (let's call it 'e') to trace the e.target

The browser's event triggering code passes that. You just need to read it.

nextClicked(e) {
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
1

"...and I cannot pass a variable (let's call it 'e') to trace the e.target"

Actually, you don't need to pass it as variable, because even if you don't pass the e you can get it in nextClicked because browsers do it by default, so it will come as parameter if you declare the function as nextClicked(e){...} and keep the bind as you have.

Or, you can pass parameters after this, such as ...bind(this, this.nextBtn), then the first parameter on nextCliked will be the button.

See below these two possibilities I mentioned:

$(".buttons").on("click", this.nextClicked.bind(this))

function nextClicked(e){
  //here your context is the same as when you binded the function, but you have the event
  let target = e.target;
  console.log(target.id);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn-1" class="buttons">click me 1</button>
<button id="btn-2" class="buttons">click me 2</button>

let nextButton = $("#btn-1")[0];
$(".buttons").on("click", this.nextClicked.bind(this, nextButton))

function nextClicked(nextBtn, e) {
  //here your context is the same as when you binded the function,
  //but you have the button AND the event
  console.log("NextButton Id: " + nextBtn.id);
  console.log("Clicked button Id: " + e.target.id);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn-1" class="buttons">next</button>
<button id="btn-2" class="buttons">previous</button>
Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
1

You are doing

this.next_fs = $(this)

But, earlier you set this to an instance of FormController

 this.nextBtn.on("click", this.nextClicked.bind(this));

so what you are doing is

 this.next_fs = $( (FormController)this);

You are expecting jQuery to work with a class instance, instead of the event object.

I strongly discourage you from using $(this) ever in a event handling context. this can change it's meaning as you have shown in your sample by the code breaking.

Always use event.target or event.currentTarget. I prefer currentTarget as it points to the element on which the event was bound, and not a deeper lying element within that element.

so your code should be

nextClicked(e) {
    this.next_fs = $(e.currentTarget)
      .parent()
      .next(); // this is the next fieldset
    // some actions...
  }
Tschallacka
  • 27,901
  • 14
  • 88
  • 133
  • I cannot use nextClicked(e) {...} because I cannot pass (e) ti the event listener (well... I believe I can't...) writing something like this.nextBtn.on("click", this.nextClicked(e).bind(this)); issues an error – Simone Conti Feb 03 '20 at 16:18
  • You don't pass the event to it. the event will call the function and then pass the event to it. All you have to do is provide the reference to the event handler, which you do. What's the error you're getting? – Tschallacka Feb 03 '20 at 16:21