I want to know if any parent-tr
child-tr
checkbox is checked then parent-tr also checked.
if window load the function check which parent-tr child is checkbox is true if is find any child checkbox true then the parent also checked.
function childRowCheck() {
const list = $("#parent-tr input:checkbox").prop("checked", true);
const childRow = $("tr.child-tr #id_ticker:checked");
childRow.each(function (i) {
return list[i]
});
}
$('tbody tr.child-tr').click(':checkbox', function (e) {
childRowCheck();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<!-- parent -->
<tr id="parent-tr">
<td><input type="checkbox" name="subject" id="subject">Parent</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr id="child-tr">
<td><input type="checkbox" name="ticker" id="ticker">Child</td>
</tr>
<tr id="child-tr">
<td><input type="checkbox" name="ticker" id="ticker">Child</td>
</tr>
<tr id="child-tr">
<td><input type="checkbox" name="ticker" id="ticker">Child</td>
</tr>
<!-- parent -->
<tr id="parent-tr">
<td><input type="checkbox" name="subject" id="subject">Parent</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr id="child-tr">
<td><input type="checkbox" name="ticker" id="ticker">Child</td>
</tr>
<tr id="child-tr">
<td><input type="checkbox" name="ticker" id="ticker">Child</td>
</tr>
<tr id="child-tr">
<td><input type="checkbox" name="ticker" id="ticker">Child</td>
</tr>
</tbody>
</table>
CodePudding user response:
You have much better control of your application, if you control the data and not the UI:
- create a data structure that best suits the relation(s) between the elements
- create a template that can be re-used to populate the DOM
The main benefit of the solution below is that you always have a correct state that you can use (e.g. 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>
CodePudding user response:
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" />Parent
</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr>
<td><input type="checkbox" name="ticker" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" />Child</td>
</tr>
<!-- parent -->
<tr>
<td>
<input type="checkbox" name="subject" />Parent
</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr>
<td><input type="checkbox" name="ticker" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" />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.