skip to Main Content

Is it possible to use "this" with the querySelector method.

I have multiple dynamic buttons on a page and need to get the data-set values for the clicked button.

<button class="user" id="1"
        data-loc="ox1"
        data-name="tom">
</button>

<button class="user" id="2"
        data-loc="ox2"
        data-name="tom-two">
</button>

I tried the below code but it only gives the first element on the page.

[...document.getElementsByClassName("user")].forEach(function(item){
        item.addEventListener("click",myFunction )
    });

 function myFunction() {
 const user = $el.querySelector(".user");
 }

I then tried using the "this" keyword but it does not work.

var $el = $(this);

const member = $el.querySelector(".user");

4

Answers


  1. In an event handler, this is already set to the element the event listener was bound to (also known as event.currentTarget). There is no need to call querySelector again.

    The data attributes can be accessed via the dataset property.

    [...document.getElementsByClassName("user")].forEach(function(item) {
      item.addEventListener("click", myFunction);
    });
    
    function myFunction() {
      console.clear();
      console.log(this.dataset);
    }
    <button class="user" id="1" data-loc="ox1" data-name="tom">
            Button 1
    </button>
    
    <button class="user" id="2" data-loc="ox2" data-name="tom-two">
            Button 2
    </button>

    Also note that it is generally recommended to use event delegation on a common ancestor instead of attaching event listeners to every individual element.

    document.querySelector('.buttons-container').addEventListener('click', e => {
      if (e.target.matches('button.user')) {
        console.clear();
        console.log(e.target.dataset);
      }
    });
    <div class="buttons-container">
      <button class="user" id="1" data-loc="ox1" data-name="tom">
        Button 1
      </button>
      <button class="user" id="2" data-loc="ox2" data-name="tom-two">
        Button 2
      </button>
    </div>
    Login or Signup to reply.
    1. No need for jQuery
    2. Also no need for spread using querySelectorAll
    3. you need to use the event passed in the function
    document.querySelectorAll('.user').forEach(function(item) {
      item.addEventListener("click", myFunction)
    });
    
    function myFunction(e) {
      const tgt = e.target.closest('button');
      if (!tgt) return; // not a button
      const userDiv = document.getElementById(tgt.dataset.name);
      console.log(userDiv.textContent)
    }
    <button class="user" id="1" data-loc="ox1" data-name="tom">Click 1</button>
    <button class="user" id="2" data-loc="ox2" data-name="tom-two">Click 2</button>
    
    <div id="tom">Tom</div>
    <div id="tom-two">Tom2</div>

    I recommend to delegate too

    document.getElementById('buttonDiv').addEventListener("click", (e) => {
      const tgt = e.target.closest('button');
      if (!tgt) return; // not a button
      const userDiv = document.getElementById(tgt.dataset.name);
      console.log(userDiv.textContent)
    })
    <div id="buttonDiv">
      <button class="user" id="1" data-loc="ox1" data-name="tom">Click 1</button>
      <button class="user" id="2" data-loc="ox2" data-name="tom-two">Click 2</button>
    </div>
    <div id="tom">Tom</div>
    <div id="tom-two">Tom2</div>
    Login or Signup to reply.
  2. It may be possible, but not desirable (using this seldom is). To simplify things, let’s use event delegation, which is especially suitable for dynamically created elements.

    document.addEventListener(`click`, handle);
    
    function handle(evt) {
      // find the button of interest
      const userBttn = evt.target.closest(`.user`);
      
      if (userBttn) {
        // retrieve and display the values of the data-attributes
        // ([Element].dataset property)
        console.log(`loc: ${userBttn.dataset.loc}, name: ${
              userBttn.dataset.name}`);
      }
    }
    <button class="user" id="1"
            data-loc="ox1"
            data-name="tom">
      user 1
    </button>
    
    <button class="user" id="2"
            data-loc="ox2"
            data-name="tom-two">
      user 2
    </button>
    Login or Signup to reply.
  3. I hope this approach can help you.

    const myClickEventFunction = myEvent =>
    {
      // Select the element that fired the event.
      const myClickedElement = myEvent.target;
      
      // Reserve the namespace for all attributes.
      const myAttributes = {};
      
      // Get the dataset attributes.
      const myDataSet = myClickedElement.dataset;
      
      // Populate myAttributes with all atrributes of myClickedElement.
      for ( const myAttribute of myClickedElement.attributes )
      {
        myAttributes[myAttribute.name] = myAttribute.value;
      }
      
      // DEBUG:
      console.clear();
      console.log('Clicked element:', myClickedElement);
      console.log('Clicked element attributes:', myAttributes);
      console.log('Clicked element dataset:', myDataSet);
    }
    
    // Select all elements with the CSS class `user`.
    const myButtons = document.querySelectorAll('.user');
    
    // Bind the myClickEventFunction to each element in myButtons.
    for ( const myButtonElement of myButtons )
    {
      myButtonElement.addEventListener('click', myClickEventFunction);
    }
    <button class="user" id="1"
            data-loc="ox1"
            data-name="tom">
            B1
    </button>
    
    <button class="user" id="2"
            data-loc="ox2"
            data-name="tom-two">
            B2
    </button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search