Yudy Ananda
Yudy Ananda

Reputation: 568

AddEventListener for Multiple Button

i have multiple user comments wrapped in <article> with the same content structure and the same class. the main part that i need to playaround with js is to get text and attribute value from each user comment when the reply button clicked then add those thing to form input value.

this is the html structure

<div class="comments">

  <article id="comment-1" class="comment parent">
    <span class='comment-author'>John Doe</span>
    <p class="body">Lorem ipsum  af farm-to-table brunch XOXO portland small batch edison bulb yr hella 3 wolf moon</p>
    <a id="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6" class="reply-btn"  title="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6">reply</a>
  </article>

  <!-- this one is reply for the first comment -->
  <article id="comment-1r1" class="comment reply">
    <span class='comment-author'>Jane</span>
    <p class="body">Lorem ipsum  af farm-to-table brunch XOXO portland small batch edison bulb yr hella 3 wolf moon</p>
    <a id="de255ea0-ddde-11e9-84d7-5d6e5fdjkl4m5" class="reply-btn"  title="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6">reply</a>
  </article>

  <article id="comment-2" class="comment reply">
    <span class='comment-author'>Foo</span>
    <p class="body">Lorem ipsum  af farm-to-table brunch XOXO portland small batch edison bulb yr hella 3 wolf moon</p>
    <a id="de255ea0-ddde-11e9-84d7-5d6e5fdj409d4" class="reply-btn"  title="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6">reply</a>
  </article>


</div>

<!-- the form -->
<form>
  <input class="replyThread" type="hidden" name="fields[replyThread]" value="">
                <input class="replyID" type="hidden" name="fields[replyID]" value="">
                <input class="replyName" type="hidden" name="fields[replyName]" value="">

</form

as you can see each user comment have a unique user name also unique attribute value on the reply-btn but they generaly they have same class.

this is my workaround

    const replyButton = document.querySelector('.reply-btn');
    const replyThread = document.querySelector('.replyThread');
    const replyID = document.querySelector('.replyID');
    const replyName = document.querySelector('.replyName');
    const threadValue = document.querySelector('.reply-btn').getAttribute("title");
    const idValue = document.querySelector('.reply-btn').getAttribute("id");
    const nameValue = document.querySelector('.comment-author');

    replyButton.addEventListener('click', (evt) => {
        replyThread.innerHTML = threadValue;
        replyID.innerHTML = idValue;
        replyName.setAttribute('value', nameValue.innerHTML );
    })

the only problem is the button seems to work only for the first comment, when i click the other nothing happen. i try using querySelectorAll but unfortunately it can work with addEventListener

my question is how to make the reply button working and get the text and attribute value from the right place (each user comment)?

Upvotes: 0

Views: 104

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370759

I'd use event delegation on the .comments container: watch for clicks, and if the clicked target matches .reply-btn, get its .title and ID, and get the thread title by accessing the .comment-author in its container, and then you can put those into the form:

const [replyThread, replyId, replyName] = document.querySelectorAll('form > *');

document.querySelector('.comments').addEventListener('click', ({ target }) => {
  if (!target.matches('.reply-btn')) {
    return;
  }
  replyId.value = target.id;
  replyThread.value = target.title;
  replyName.value = target.parentElement.querySelector('.comment-author').textContent;
});
<div class="comments">

  <article id="comment-1" class="comment parent">
    <span class='comment-author'>John Doe</span>
    <p class="body">Lorem ipsum af farm-to-table brunch XOXO portland small batch edison bulb yr hella 3 wolf moon</p>
    <a id="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6" class="reply-btn" title="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6">reply</a>
  </article>

  <!-- this one is reply for the first comment -->
  <article id="comment-1r1" class="comment reply">
    <span class='comment-author'>Jane</span>
    <p class="body">Lorem ipsum af farm-to-table brunch XOXO portland small batch edison bulb yr hella 3 wolf moon</p>
    <a id="de255ea0-ddde-11e9-84d7-5d6e5fdjkl4m5" class="reply-btn" title="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6">reply</a>
  </article>

  <article id="comment-2" class="comment reply">
    <span class='comment-author'>Foo</span>
    <p class="body">Lorem ipsum af farm-to-table brunch XOXO portland small batch edison bulb yr hella 3 wolf moon</p>
    <a id="de255ea0-ddde-11e9-84d7-5d6e5fdj409d4" class="reply-btn" title="de255ea0-ddde-11e9-84d7-5d6e5fd4ffd6">reply</a>
  </article>


</div>

<!-- the form -->
<form>
  Form
  <input class="replyThread" name="fields[replyThread]" value="">
  <input class="replyID" name="fields[replyID]" value="">
  <input class="replyName" name="fields[replyName]" value="">

</form>

While querySelectorAll is possible too, it'd require adding a separate listener to each button, which is overkill. (event delegation also allows for functionality for dynamically added elements too).

Upvotes: 2

Related Questions