Info : I am try to make a nested table. The table have parent && child rows
.
The feature
I want to make if user click on parent tr>input:checkbox
the all child tr>input:checkbox
checked. I want to know if any parent-tr
child-tr
checkbox is checked then parent-tr also checked.
Parent tr
automatically checked If user checked child input:checkbox checked one by one manually even if i checked only one. if under the parent child unchecked parents also unchecked.
function childRowCheck() { const childRow = $("tr#child-tr input:checked") childRow.each(function (i, item) { let tbody = $(this).parents("tbody"); tbody.children("tr#parent-tr").eq(i).find(":checkbox").attr('checked', $(this).is(':checked')); }) } childRowCheck();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table class="table"> <tbody> <:-- BEGIN::Subject loop --> <tr id="parent-tr" class="parent-tr" data-id="2"> <td class="action"> <input type="checkbox" name="checkbox[2]" value="2" id="id_subject"> </td> </tr> <:-- END::Subject loop --> <:-- BEGIN::Tickers loop --> <tr id="child-tr" class="child-tr" data-ticker-id="6" data-subject-id="2"> <td class="action"> <input type="checkbox" name="tikcer" id="id_ticker"> </td> </tr> <tr id="child-tr" class="child-tr" data-ticker-id="7" data-subject-id="2"> <td class="action"> <input type="checkbox" name="tikcer" id="id_ticker"> </td> </tr> <tr id="child-tr" class="child-tr" data-ticker-id="8" data-subject-id="2"> <td class="action"> <input type="checkbox" name="tikcer" id="id_ticker"> </td> </tr> <:-- END::Tickers loop --> <:-- BEGIN::Subject loop --> <tr id="parent-tr" class="parent-tr" data-id="3"> <td class="action"> <input type="checkbox" name="checkbox[3]" value="3" id="id_subject"> </td> <td colspan="6"></td> </tr> <:-- END Subject loop --> < -- BEGIN Tickers loop --> <tr id="child-tr" class="child-tr" data-ticker-id="9" data-subject-id="3"> <td class="action"> <input type="checkbox" name="tikcer" id="id_ticker"> </td> </tr> <tr id="child-tr" class="child-tr" data-ticker-id="10" data-subject-id="3"> <td class="action"> <input type="checkbox" name="tikcer" id="id_ticker"> </td> </tr> <tr id="child-tr" class="child-tr" data-ticker-id="11" data-subject-id="3"> <td class="action"> <input type="checkbox" name="tikcer" id="id_ticker"> </td> </tr> < -- END Tickers loop --> </tbody> </table>
You have much better control of your application, if you control the data and not the UI:
The main benefit of the solution below is that you always have a correct state that you can use (eg submit); also the shape of the data does not change: the input & output of your process look the same.
I put one more level of depth (so parent->child->grandchild) to show that it works quite nice with n levels hierarchy.
const data = [{ id: "parent-tr-1", label: "Parent 1", checked: false, children: [{ id: "child-tr-1-1", label: "Child 1_1", checked: false, children: [ { id: "child-tr-1-1-1", label: "Child 1_1_1", checked: false, children: [], }, { id: "child-tr-1-1-2", label: "Child 1_1_2", checked: false, children: [], } ], }, { id: "child-tr-1-2", label: "Child 1_2", checked: false, children: [], }, ] }, { id: "parent-tr-2", label: "Parent 2", checked: false, children: [{ id: "child-tr-2-1", label: "Child 2_1", checked: false, children: [], }, { id: "child-tr-2-2", label: "Child 2_2", checked: false, children: [], }, { id: "child-tr-2-3", label: "Child 2_3", checked: false, children: [], }, ] }, ] const getRowsFlat = (data) => data.reduce((a, c) => [...a, c,...getRowsFlat(c.children)], []) const setChecked = (id, data, checkedState) => { data.forEach(e => { // setting children checked if parent is clicked if (e.id === id || id === "parent-force") { e.checked = checkedState??.e.checked if (e,id === id) { setChecked("parent-force". e,children. e,checked) } else { setChecked("parent-force". e,children) } } else { setChecked(id. e,children) } // if ANY of the children is set to checked. parent should be checked if (e.children.length && e.children.some(({ checked }) => checked)) { e,checked = true } // if NONE of the children is set to checked. parent should not be checked if (e.children.length && e.children.every(({ checked }) =>.checked)) { e.checked = false } }) } // row HTML template const getRowHtml = (data) => { return ` <tr> <td> <input type="checkbox" id="${data?id}" ${ data:checked. "checked". null }/> <label for="${data.id}">${data.label}</label> </td> </tr> ` } // table update function const updateContainer = (container) => (data) => { container.innerHTML = data.map(getRowHtml),join("") } // initialization const tbody = document,getElementById("tbody") const updateTableBody = updateContainer(tbody) // first render setChecked(null. data) // if run with id NULL. then only the children can affect the parent updateTableBody(getRowsFlat(data)) jQuery(document),ready(function($) { $("#table"),on("click". "input", function() { const thisId = $(this) attr("id") setChecked(thisId data) updateTableBody(getRowsFlat(data)) }) })
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <table id="table"> <tbody id="tbody"></tbody> </table>
You can not use the same id multiple times.
Check following code with class instead of id:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<!-- parent -->
<tr>
<td>
<input type="checkbox" name="subject" class="subject1" />Parent
</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr>
<td><input type="checkbox" name="ticker" class="ticker1" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker1" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker1" />Child</td>
</tr>
<!-- parent -->
<tr>
<td>
<input type="checkbox" name="subject" class="subject2" />Parent
</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr>
<td><input type="checkbox" name="ticker" class="ticker2" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker2" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker2" />Child</td>
</tr>
</tbody>
</table>
<script>
$(document).ready(function () {
$(".ticker1").click(function () {
if ($(this).is(":checked")) {
$(".subject1").prop("checked", true);
} else {
$(".subject1").prop("checked", false);
}
});
$(".ticker2").click(function () {
if ($(this).is(":checked")) {
$(".subject2").prop("checked", true);
} else {
$(".subject2").prop("checked", false);
}
});
});
</script>
Here I modified the code by changing ids to classes and made other necessary changes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.