Как добавить слушателя события для нескольких кнопок, которые отображаются с помощью цикла for?
У меня есть страница, на которой отображаются посты пользователей в социальных сетях, и все посты имеют кнопку Edit. При нажатии на кнопку Edit отображается форма с текстовой областью, предварительно заполненной текущим содержимым, и входом для отправки.
Проблема в том, что независимо от того, на какую кнопку редактирования сообщения я нажимаю, всегда изменяется первое сообщение. Я предполагаю, что мне нужно добавить где-то "id", чтобы отслеживать, какой пост редактируется, но я не смог понять, как это сделать. Или есть другое решение?
views.py:
def index(request):
post_list = AllPost.objects.all().order_by("date").reverse()
paginator = Paginator(post_list, 10) # Show 10 posts per page.
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, "network/index.html", {
"posts": post_list,
"page_obj": page_obj
})
def edit(request, id):
if request.method == "POST":
new_content = request.POST["new_content"]
updated_post = AllPost.objects.filter(id = id)
updated_post.update(content = new_content)
return JsonResponse({}, status = 201)
return JsonResponse({"error": "Bad Request"}, status = 400)
index.html:
{% for post in page_obj %}
{{ post.full_name|upper }}<br>
<div class="frame">
<h4><a href="{% url 'profile' post.user.username %}" style="color: black;">{{post.user.username}}</a></h4>
{% if post.user == user %}
<button class="btn btn-sm btn-outline-primary" id="edit">Edit</button>
{% endif %}
<div id="content">{{post.content}}</div>
<form action="{% url 'edit' post.id %}" method="post" id="edit_post" style="display: none;">
{% csrf_token %}
<div class="form-group"><textarea id="new_content" name="new_content" cols="30"></textarea></div>
<input class="btn btn-sm btn-primary" id="save" type="submit" value="Save">
</form>
<div class="grey" id="timestamp">{{post.date}}</div>
<div class="grey">{{post.likes}}</div>
<a href="#" style="color: grey;">Comment</a>
</div>
{% endfor %}
network.js
document.addEventListener("DOMContentLoaded", () => {
document.querySelector("#content").innerHTML = localStorage.getItem("content");
document.querySelectorAll("#edit").forEach(button => {
button.onclick = () => {
const content = document.querySelector("#content").innerHTML;
document.querySelector("#content").style.display = "none";
document.querySelector("#edit_post").style.display = "block";
document.querySelector("#new_content").value = content;
}
});
document.querySelector("#edit_post").onsubmit = (event) => {
let content = document.querySelector("#new_content").value;
document.querySelector("#content").innerHTML = content;
document.querySelector("#content").style.display = "block";
document.querySelector("#edit_post").style.display = "none";
event.preventDefault();
localStorage.setItem("content", content);
};
});
Просто удалите абсолютные id-селекторы, потому что с абсолютным id-селектором вы просто получите всегда первый элемент с этим id. Поэтому замените его на относительный class-селектор. Также я рекомендую вам использовать addEventListener
вместо on<event>
.
Измените .html
на следующее:
{% for post in page_obj %}
{{ post.full_name|upper }}<br>
<div class="frame">
<h4><a href="{% url 'profile' post.user.username %}" style="color: black;">{{post.user.username}}</a></h4>
{% if post.user == user %}
<button class="btn btn-sm btn-outline-primary edit">Edit</button>
{% endif %}
<div class="content">{{post.content}}</div>
<form action="{% url 'edit' post.id %}" method="post" class="edit_post" style="display: none;">
{% csrf_token %}
<div class="form-group"><textarea class="new_content" name="new_content" cols="30"></textarea></div>
<input class="btn btn-sm btn-primary" id="save" type="submit" value="Save">
</form>
<div class="grey" id="timestamp">{{post.date}}</div>
<div class="grey">{{post.likes}}</div>
<a href="#" style="color: grey;">Comment</a>
</div>
{% endfor %}
Измените .js
на следующее:
document.addEventListener("DOMContentLoaded", () => {
document.querySelector(".content").innerHTML = localStorage.getItem("content");
Array.from(document.querySelectorAll(".edit")).forEach(button => {
button.addEventListener('click', event => {
const target = event.target
const frame = target.closest('.frame')
const content = frame.querySelector('.content')
const edit_post = frame.querySelector('.edit_post')
edit_post.style.display = 'block'
const new_content = frame.querySelector('.new_content')
new_content.value = content.textContent
content.style.display = 'none'
})
const form = button.closest('.frame').querySelector('.edit_post')
form.addEventListener('submit', event => {
const target = event.target
const frame = target.closest('.frame')
const content = frame.querySelector('.content')
content.innerHTML = content
content.style.display = 'block'
const edit_post = frame.querySelector('.edit_post').style.display = 'none'
localStorage.setItem('content', content)
event.preventDefault()
})
});
});