问题描述
当用户单击父 li 中的任意位置时,我需要检查一个单选按钮。 ul 在原始 html 中,但 li 和单选按钮在下面的函数 (displaySearchResults(responseJson)) 内的 for 循环中呈现给 DOM。
无法对特定点击的 li 的单选按钮应用任何更改(有时能够更改所有单选按钮)——使用 this 关键字或各种类/ID/元素组合来定位点击 li。
这里是事件监听器,后面是相关代码。
这绝对是一场噩梦,感谢您的帮助。谢谢!
EVENT LISTENER
function select(){
$('.results-list-item').click(event => {
let name = $(this)
console.log('li click')
//varIoUs attempts at marking the child radio button as checked
//$(this).closest($('input')).prop("checked",true)
//$(this).children($('input')).attr('checked','true')
$('.results-list-item').children($('input.radio')).attr('checked','')
})
};
function displaySearchResults(responseJson) {
for (let i = 0; i < 10; i++){
$('#results-list').append(
`
<li class='results-list-item'>
<h3>${results[i].name}</h3>
<input type='radio' id='${results[i].name}' value='${responseJson.results[i].id}' required>
</li>
`
)
}
select()
}
HTML
<main class='container'>
<section id='results'>
<form id='js-results-form'>
<ul id='results-list'>
</ul>
<input type='submit' value='Select Game'></input>
</form>
</section>
</main>
解决方法
Tl;博士::
- 您不需要任何 JS 点击侦听器,只需使用
<label>
作为包装器。 - PS:
$collection.click()
仅适用于已经存在的(在 DOM 就绪时)元素。您的元素是动态生成的:因此使用 .on() 方法:$staticParent.on("eventName","dynamicChild",fn)
好的;你::
- 完全删除您的
functionSelect()
- 改为使用带有 delegated event handlers 的 jQuery
.on()
方法,以便为从特定当前 或将来 元素触发的事件的静态父元素分配侦听器目标。 - 在处理程序中使用
ev.preventDefault();
以防止标签或复选框/或无线电回火 - 如何使您的 LI 可点击?您不必这样做,只需使用 HTML
<label>
元素并将其在 CSS 中设置为display: block;
// How it works:
// "Static parent" on "evtName" "dynamic child"
$('#results-list').on("click",".results-list-item",function(ev) {
console.log(this); // The LI Element
console.log(ev.currentTarget); // The LI element
console.log(ev.delegateTarget); // The static UL Element
console.log(ev.target); // Some Element dispatcher,who knows...
});
此外,用于显示 LI 结果:
// Elements
const $resultsList = $('#results-list');
// Templates
const tpl_item = (item) => `<li class='results-list-item'>
<label>
<span>${item.name}</span>
<input type="checkbox" name="${item.name}" value="${item.id}" required>
</label>
</li>`;
// UI
const UI_displaySearchResults = (responseJson) => {
const html_listItems = responseJson.reduce((s,item) => s + tpl_item(item),"");
$resultsList.append(html_listItems);
};
// Events
$resultsList.on("click","li",function(ev) {
ev.preventDefault(); // Prevent label (input) firing twice
console.log(this.textContent.trim()); // The LI element content,if needed?
});
// Finally: on Init or on AJAX request,does not matters any more:
UI_displaySearchResults([
{id: 4,name: "Lorem ipsum"},{id: 9,name: "Dolor dolor,dolor"},{id: 8,name: "Sit amet"},]);
#results-list label {
display: block;
}
li:hover {
background: gold; /* demo only */
}
<ul id="results-list"></ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
我查看了您的问题,也许您可以仅使用 HTML 解决它,假设输入上有文本,您可以添加标签并使用道具“for”将文本链接到输入
我还借此机会更正了您最终遗漏的一个细节,当您调用 ${results[i].name}
时,responseJson 丢失了
像下面的例子:
$('#results-list').append(
`
<li class='results-list-item'>
<h3>${responseJson.results[i].name}</h3>
<label for='${responseJson.results[i].id}'>
<input type='radio' id='${responseJson.results[i].id}' value='${responseJson.results[i].name}' required>
${responseJson.results[i].name}
</label>
</li>
`
)
希望有所帮助!