0

I am trying to select an HTML button that is within a for loop in a Django template using a querySelector to add an event listener to it in JavaScript. How do you create a unique id for the button and select it through JavaScript? Right now, I have one id set to the button within the for loop, and when you press the button, nothing happens.

html

% for post in page_obj.object_list %}
            <div class = "individual_posts">
                <a href="{% url 'username' post.user %}"><h5 class = "post_user">{{ post.user }}</h5></a>
                <h6 id = "post_itself">{{ post.post }}</h6>
                {% if post.user == request.user %}
                    <button id="editButton" class="edit_button">Edit</button>
                {% endif %}
            </div>
        {% endfor %}

JavaScript

document.addEventListener('DOMContentLoaded', function(){
    document.querySelector('#editButton').onclick = edit_email();
})
econo
  • 49
  • 7
  • Nothing is happening when you click because your `onclick` should be the function `edit_email` - as it is, you're calling it to early. But you're also repeating an ID multiple times in the document, which is invalid and won't work here. You should use a class instead, and use `querySelectorAll` or `getElementsByClassName` to loop through them all and add the `onclick` to each. (It's also better practice to use `addEventListener` than to assign to the `onclick` property.) – Robin Zigmond Jul 14 '22 at 20:21
  • @RobinZigmond [`getElementsByClassName()`](https://stackoverflow.com/questions/54952088/how-to-modify-style-to-html-elements-styled-externally-with-css-using-js/54952474#54952474) should definitely not be used, especially in conjunction with a loop. – Scott Marcus Jul 14 '22 at 20:23

1 Answers1

-1

All of your buttons will have the same HTML id, one easy way of differentiating would be to include the forloop counter like so:

id="editButton{{ forloop.counter0 }}"

Then you can specify the button in your javascript.

However, I imagine you want to add the onclick functionality to all buttons. Your JS is selecting based on id using the # selector, if you change it to ('.edit_button') it should work for all buttons

0sVoid
  • 2,547
  • 1
  • 10
  • 25
  • `id`s should generally be avoided in the first place as they create brittle code that doesn't scale well. Dynamic `id`s are an anti-pattern. – Scott Marcus Jul 14 '22 at 20:24
  • Hence the recommendation to use a class selector – 0sVoid Jul 14 '22 at 20:25
  • @OsVoid, I changed the code to this: ```document.querySelector('.edit_button').addEventListener('click', () => edit_email());```. Nothing still happens, but I get this error ```GET http://127.0.0.1:8000/favicon.ico 404 (Not Found)```. Do you know how to fix this? – econo Jul 14 '22 at 20:30
  • Might be a problem with your `edit_email()` code - the 404 is a separate issue that your favicon url can't be found – 0sVoid Jul 14 '22 at 20:34
  • favicon is the webpage icon you see at the top of your web browser, here's a useful answer https://stackoverflow.com/questions/21938028/how-can-i-get-a-favicon-to-show-up-in-my-django-app – 0sVoid Jul 14 '22 at 20:43
  • @OsVoid, I am no longer getting that error, but still nothing happens when you click the button. – econo Jul 14 '22 at 20:44
  • If you replace `edit_email()` with `console.log("test")`, does 'test' appear in the console when you click the button? – 0sVoid Jul 14 '22 at 20:48
  • @OsVoid, nothing happens in the console when I hit the button; 'test' doesn't appear either. – econo Jul 14 '22 at 20:51
  • I've inserted your html button and JS code into my own browser and it works fine, do you still have 'edit_button' as your button class? – 0sVoid Jul 14 '22 at 21:04
  • @0sVoid, I have ```document.querySelector('.edit_button').addEventListener('click', () => console.log("test"));```, but nothing happens in the console. – econo Jul 14 '22 at 21:22
  • It should work, make sure your queryselector is `.edit_button` but the button class `edit_button` i.e. don't put the '.' in the actual class – 0sVoid Jul 15 '22 at 08:16