简体   繁体   中英

Using $this keyword to add/remove class on onChange using jquery

Here I am trying to add a few classes in this ".ingradient" class element when ".tt-select" select changes. So, I was almost there. But when I select the option, there is a list of ".ingradient" items. I need to perform the below code for that specific one who we selected currently. I know we can use $this keyword, But I can't write the code for it. Please help. Thanks

$('.tt-select').change(function(){
  $('.ingradient').addClass('animate__animated animate__heartBeat');
const remClass = setTimeout(fnRemClass, 2000);
function fnRemClass() {
  $('.ingradient').removeClass('animate__animated animate__heartBeat');
}
});

What I've tried yet but no success.

$('.tt-select').change(function(){
$('.ingradient', this).addClass('animate__animated animate__heartBeat');

const remClass = setTimeout(fnRemClass, 2000);
function fnRemClass() {
  $('.ingradient', this ).removeClass('animate__animated animate__heartBeat');
}
});

Here is the ".tt-select" select fields.

And here is the ".ingradient" class where I need to add classes individually.

Hope, someone can help me to find out how I can use $this keyword properly here. Thanks

[EDIT] After receiving a suggestion on comments I tried this still with no success:

$('.tt-select').change(function(){  
  $(this).find(':selected')
    .addClass('animate__animated animate__heartBeat');
  const remClass = setTimeout(fnRemClass, 2000);
  function fnRemClass() { 
    $(this).find(':selected')
      .removeClass('animate__animated animate__heartBeat');
  }
}); 

First things first: options can't be styled

First things first: I should say that you can't properly style <option> elements. I mean it's still legit of course to use classes and perform selection based on such criteria, but the styling itself is very limited for the options. That's why usually very stylish dropdowns are actually custom elements on top of real <select> elements. But yet it's perfectly legit to use them as utility classes.

Function type and scope at time of execution:

Said that...

The problem with your latest approach was trying to use this inside the callback defined inside your change event handler that you are going to pass later to setTimeout .

Such function at time of execution will have this set as window hence the .find operation won't perform returning the desired result. It will instead fetch ALL elements matching that selector in the umbrella of window (global scope).

While instead you needed to retain the scope of the targeted select element.

The quick solution to your problem is properly defining a callback that will retain the correct scope and that will access directly to the variable already holding the selected option instead of querying again the document.

Here I simplified your example adding/removing just one class and having two different dropdowns to show that while doing something on one dropdown the other doesn't get affected.

I used a variable named $selectedOption (using the $ just because it was a convention back then to mark it as a jQuery wrapper object instead of the vanilla HTMLElement) that gets reused inside the callback:

 $('.tt-select').change(function(){ //fetching the selected option for the dropdown firing the change event const $selectedOption = $(this).find(':selected'); $selectedOption.addClass('customclass'); console.log('class added to selected option') const callback = ()=>{ $selectedOption.removeClass('customclass'); console.log('class removed from selected option') }; setTimeout(callback, 2000); });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <select class="tt-select"> <option value="" selected></option> <option value="option1">option1</option> <option value="option2">option2</option> <option value="option3">option3</option> </select> <select class="tt-select"> <option value="" selected></option> <option value="option1">option1</option> <option value="option2">option2</option> <option value="option3">option3</option> </select>

And here I made a very simple demo showing different ways to define functions that will log on console a different value of this (I'm using .constructor.name to show off the type of the value):

 $('.tt-select').change(function(){ console.log(`change event handler... 'this' value type: [${this.constructor.name}]`); //fetching the selected option for the dropdown firing the change event const selectedOption = $(this).find(':selected'); //callback defined with the function notation and no variable set explicitely function callback1(){ console.log(`Callback[1] executing... 'this' value type: [${this.constructor.name}]`); }; //callback defined with the function notation setting the scope variable callback2 const callback2 = function(){ console.log(`Callback[2] executing... 'this' value type: [${this.constructor.name}]`); }; //callback defined as an arrow function setting the variable callback3 const callback3 = ()=>{ console.log(`Callback[3] executing... 'this' value type: [${this.constructor.name}]`); }; setTimeout(callback1, 500); setTimeout(callback2, 500); setTimeout(callback3, 500); });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <select class="tt-select"> <option value="" selected></option> <option value="option1">option1</option> <option value="option2">option2</option> <option value="option3">option3</option> </select>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM