英文:
Only the first button fires with AJAX and EJS
问题
这是您提供的代码的翻译:
EJS模板:
<link rel="stylesheet" href="../css/categorieslist.css">
<article class="post-item" id="<%= user.UserID %>" data-userId="<%= user.UserID %>">
<p>
<%= user.Email %>
<input type="hidden" class="hiddenField" id="userid" name="userid" value="<%= user.UserID %>" required>
<p><%= user.UserID %></p>
<a class="btn catbtn" href="/admin-usercategories/<%= user.UserID %>/edit">编辑调用</a>
<div class="categorieslist">
<% for (const cat of categories) { %>
<p>
<input type="checkbox" id="<%= cat.CategoryID %>" value="<%= cat.CategoryID %>">
<label for="<%=cat.CategoryID %>"><%= cat.CategoryName %></label>
</p>
<% } %>
</div>
</p>
</article>
<script type="text/javascript" src="/javascript/usercategories.js" charset="utf-8"></script>
JavaScript文件:
const btn = document.querySelector(".catbtn");
const displayElement = document.querySelector(".categorieslist");
btn.addEventListener('click', function() {
fetchUserCategories();
});
async function fetchUserCategories() {
if (displayElement.style.display === "none") {
displayElement.style.display = "block";
} else {
displayElement.style.display = "none";
}
}
如果您有其他问题或需要进一步的帮助,请随时告诉我。
英文:
I have a EJS template which gets included on a page by running a for loop. Each template has a link which when clicked should toggle the display/hiding of a number of checkboxes. I am trying to use AJAX and have a javascript file which is linked to the template. In this javascript file I add an eventlistener to the link on that template. However only the link on the first template on the page fires.
The EJS template:
<link rel="stylesheet" href="../css/categorieslist.css">
<article class="post-item" id="<%= user.UserID %>" data-userId="<%= user.UserID %>">
<p>
<%= user.Email %>
<input type="hidden" class="hiddenField" id="userid" name="userid" value="<%= user.UserID %>" required>
<p><%= user.UserID %></p>
<a class="btn catbtn" href="/admin-usercategories/<%= user.UserID %>/edit">Edit Call</a>
<div class="categorieslist">
<% for (const cat of categories) { %>
<p>
<input type="checkbox" id="<%= cat.CategoryID %>" value="<%= cat.CategoryID %>">
<label for="<%=cat.CategoryID %>"><%= cat.CategoryName %></label>
</p>
<% } %>
</div>
</p>
</article>
<script type="text/javascript" src="/javascript/usercategories.js" charset="utf-8"></script>
The javascript file:
const btn = document.querySelector(".catbtn");
const displayElement = document.querySelector(".categorieslist");
btn.addEventListener('click', function() {
fetchUserCategories();
});
async function fetchUserCategories() {
if (displayElement.style.display === "none") {
displayElement.style.display = "block";
} else {
displayElement.style.display = "none";
}
}
答案1
得分: 0
> 不过,只有页面上第一个模板的链接会触发。
因为只有一个元素附加了点击处理程序。这会找到一个元素:
const btn = document.querySelector(".catbtn");
甚至变量名称都暗示着这一点。然后变量的使用表明它只是一个元素:
btn.addEventListener('click', function() {
fetchUserCategories();
});
如果您想要找到多个元素,您需要使用querySelectorAll
:
const btns = document.querySelectorAll(".catbtn");
然后循环遍历结果以附加点击处理程序:
for (let btn of btns) {
btn.addEventListener('click', function() {
fetchUserCategories();
});
}
当然,这将导致下一个问题... 每个按钮都执行完全相同的操作。它在第一个displayElement
上“获取用户类别”。您可能希望获取被点击元素的紧邻兄弟元素。例如,您可以将nextElementSibling
传递给函数:
for (let btn of btns) {
btn.addEventListener('click', function() {
fetchUserCategories(this.nextElementSibling);
});
}
然后在fetchUserCategories
函数中使用该元素引用:
function fetchUserCategories(displayElement) {
// “displayElement”被传递到函数中
}
如果标记可能会更改,那么您可能希望尝试其他方法来获取兄弟元素。例如:
技术通常包括从当前元素(this
)开始,向上遍历DOM到一个共同的父元素,然后从该父元素中选择目标元素。
英文:
> However only the link on the first template on the page fires.
Because a click handler is only being attached to one element. This finds an element:
const btn = document.querySelector(".catbtn");
Even the variable name implies this. And then the usage of the variable indicates that it's just one element:
btn.addEventListener('click', function() {
fetchUserCategories();
});
If you want to find multiple elements, you want querySelectorAll
:
const btns = document.querySelectorAll(".catbtn");
Then loop over the results to attach the click handlers:
for (let btn of btns) {
btn.addEventListener('click', function() {
fetchUserCategories();
});
}
Of course, this will lead to the next problem... Every button does exactly the same thing. It "fetches user categories" on the first displayElement
. You probably want the immediate sibling element of the one which was clicked. For example, you might pass the nextElementSibling
to the function:
for (let btn of btns) {
btn.addEventListener('click', function() {
fetchUserCategories(this.nextElementSibling);
});
}
And then in fetchUserCategories
use that element reference:
function fetchUserCategories(displayElement) {
// "displayElement" was passed to the function
}
If the markup could change then you might want to try other approaches to get the sibling element. For example:
- How to get sibling element by its class name and then hide it using Javascript only?
- get nearby sibling in javascript
Techniques often include starting from the current element (this
), traversing up the DOM to a common parent element, then selecting the target element from that parent.
答案2
得分: 0
由于有更多与具有类别"catbtn"的按钮相同结构的模板。 您可以更新代码的这部分:
const btns = document.querySelectorAll(".catbtn");
const displayElement = document.querySelector(".categorieslist");
for(let btn of btns){
btn.addEventListener('click', function() {
fetchUserCategories();
});
}
英文:
As there are more templates that have same structure with button having class catbtn. Then you can update this part of your code:-
const btns = document.querySelectorAll(".catbtn");
const displayElement = document.querySelector(".categorieslist");
for(let btn of btns){
btn.addEventListener('click', function() {
fetchUserCategories();
});
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论