Home > other >  Vanilla Javascript: How to add multiple event listeners to buttons which are dynamically created wit
Vanilla Javascript: How to add multiple event listeners to buttons which are dynamically created wit

Time:12-08

I am currently working on a project 4 for CS50w - Network. One of the tasks is to add an edit posts button (for editing the posts that logged in user (only owner) created), which does this async. Since for storing posts I'm using Django Models, I'm using Django (and it's template capabilities) to display all the posts to users too, and an edit button (if user is the creator of the post too). I'm displaying all the posts in a div. This means that the button for editing is also a part of this div... meaning that I can give it only single class or id for referencing, but then I don't know how to distinguish between them, and how to know which one (from which post) is clicked so that I can edit that post and not the first one on which the JS in DOM comes up... Anyways here's the code:

HTML in Django:

{% for post in posts %}
        <div class="post">
            <a href="{% url 'users' post.user.username %}">{{ post.user }}</a>
            <p>{{ post.content }}</p>
            <p>{{ post.created }}</p>
            {% if user.is_authenticated and user == post.user %}
                <button class="edit_post_button">Edit Post</button>
            {% endif %}
        </div>
        <div class="edit_post" style="display: none;">
            <a href="{% url 'users' post.user.username %}">{{ post.user }}</a>
            <textarea rows=3 cols=20>{{ post.content }}</textarea>
            <p>{{ post.created }}</p>
            <button class="save_edit_post_button">Save</button>
        </div>
{% endfor %}

and here is the little JS that I wrote that doesn't work (I'm just starting to learn it, and would like to finish this project with vanilla JS):

 document.addEventListener('DOMContentLoaded', function() {
        document.querySelectorAll('.edit_post_button').forEach(edit_post_button => {
            edit_post_button.addEventListener('click', edit_post);
        })
    });
    
    function edit_post(event) {
        document.querySelector('.post').style.display = 'none';
        document.querySelector('edit_post').style.display = 'block';
    }

CodePudding user response:

Delegation is the answer

Note you forgot a dot in document.querySelector('edit_post')

window.addEventListener('load', function() {
  document.getElementById('postContainer').addEventListener('click', function(e) {
    const tgt = e.target.closest('.edit_post_button')
    if (tgt) {
      const postDiv = tgt.closest('.postDiv')
      postDiv.querySelector('.post').hidden = true
      postDiv.querySelector('.edit_post').hidden = false
      console.log(tgt.dataset.id); // if needed
    }
  })
})
<div id="postContainer">
  <div class="postDiv">
    <div class="post">
      <a href="User1URL">user 1</a>
      <p>Post 1 </p>
      <p>yesterday</p>
      <button class="edit_post_button" data-id="postId1">Edit Post</button>
    </div>
    <div class="edit_post" hidden>
      <a href="User1URL">user 1</a>
      <textarea rows=3 cols=20>Post 1</textarea>
      <p>Yesterday</p>
      <button class="save_edit_post_button">Save</button>
    </div>
  </div>
  <div class="postDiv">
    <div class="post">
      <a href="User2URL">user 2</a>
      <p>Post 2 </p>
      <p>yesterday</p>
      <button class="edit_post_button" data-id="postId2">Edit Post</button>
    </div>
    <div class="edit_post" hidden>
      <a href="User2URL">user 2</a>
      <textarea rows=3 cols=20>Post 2</textarea>
      <p>Yesterday</p>
      <button class="save_edit_post_button">Save</button>
    </div>
  </div>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related