I am creating hierarchy relations list with parent Childs and sub-childs if i checked parent then all Childs with checked but i clicked on Childs then sub-childs will be checked. everything is working fine but its work on second click not working on first click. here is my fiddle example. fiddle link here http://jsfiddle.net/fahadsheikh/qdkwy0s7/8/
function changeCategoryStatus(_this, id) {
var main = document.querySelector(".main-checkbox"+id);
var children = document.querySelectorAll(".sub-checkbox"+id);
function toggleCheck() {
var array=[];
children.forEach(child => {
if($(this).prop("checked") == true){
child.checked = child.checked = true
}
else if($(this).prop("checked") == false){
child.checked = child.checked = false
}
array.push(child.value);
})
return array;
}
if(main){
main.addEventListener("click", toggleCheck);
}
//for sub-parent category
var sub_parent = document.querySelector(".sub-parent"+id);
var sub_children = document.querySelectorAll(".sub-checkbox"+id);
function toggleCheck() {
var array=[];
sub_children.forEach(child => {
if($(this).prop("checked") == true){
child.checked = child.checked = true
}
else if($(this).prop("checked") == false){
child.checked = child.checked = false
}
array.push(child.value);
})
return array;
}
if(sub_parent){
sub_parent.addEventListener("click", toggleCheck);
}
var status = $(_this).prop('checked') == true ? 'active' : 'inactive';
$.ajax({
type: 'POST',
url:"{{url('admin/categories-status')}}",
data: {
id: id,
status: status,
_token: "{{ csrf_token() }}"
},
success: function (result) {
$("#status-success").show();
$("#status-success").html(result.success);
setTimeout(function() {
$("#status-success").hide()
}, 3000);
}
});
}
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#banner-message {
background: #fff;
border-radius: 4px;
padding: 20px;
font-size: 25px;
text-align: center;
transition: all 0.2s;
margin: 0 auto;
width: 300px;
}
button {
background: #0084ff;
border: none;
border-radius: 5px;
padding: 8px 14px;
font-size: 15px;
color: #fff;
}
#banner-message.alt {
background: #0084ff;
color: #fff;
margin-top: 40px;
width: 200px;
}
#banner-message.alt button {
background: #fff;
color: #000;
}
<div class="sortable">
<div class="group-caption">
<li class="main-parent category-sortable main-item" data-parent="4" data-position="4" data-newposition="1">second room
<span class="buttons-align">
<label class="switch">
<input class="main-checkbox4" type="checkbox" id="user-4"
onclick="changeCategoryStatus(event.target, 4);"
>
<span class="slider round"></span>
</label>
</span>
<div class="move" id="item-move" ><i class="fa fa-bars" aria-hidden="true"></i></div></li>
<ul class="group-items group-items-parent">
<li class="group-item-parent category-sortable" data-parent="5" data-position="1" data-newposition="1">second-child room
<span class="buttons-align">
<label class="switch">
<input class="sub-checkbox4 sub-parent4" type="checkbox" id="user-5"
onclick="changeCategoryStatus(event.target, 5);"
>
<span class="slider round"></span>
</label>
</span>
<div class="move"><i class="fa fa-bars" aria-hidden="true"></i></div></li>
<ul class="group-items-child">
<li class="group-item-child category-sortable" data-parent="6" data-position="1" data-newposition="0">second subchild
<span class="buttons-align">
<label class="switch">
<input class="sub-checkbox4" type="checkbox" id="user-6"
onclick="changeCategoryStatus(event.target, 6);"
>
<span class="slider round"></span>
</label>
</span>
<div class="move"><i class="fa fa-bars" aria-hidden="true"></i></div></li>
</ul>
</ul>
</div>
<div class="group-caption">
<li class="main-parent category-sortable main-item" data-parent="7" data-position="4" data-newposition="2">third-room
<span class="buttons-align">
<label class="switch">
<input class="main-checkbox7" type="checkbox" id="user-7"
onclick="changeCategoryStatus(event.target, 7);"
>
<span class="slider round"></span>
</label>
</span>
<div class="move" id="item-move" ><i class="fa fa-bars" aria-hidden="true"></i></div></li>
<ul class="group-items group-items-parent">
<li class="group-item-parent category-sortable" data-parent="9" data-position="1" data-newposition="1">third-child
<span class="buttons-align">
<label class="switch">
<input class="sub-checkbox7 sub-parent7" type="checkbox" id="user-9"
onclick="changeCategoryStatus(event.target, 9);"
>
<span class="slider round"></span>
</label>
</span>
<div class="move"><i class="fa fa-bars" aria-hidden="true"></i></div></li>
<ul class="group-items-child">
<li class="group-item-child category-sortable" data-parent="10" data-position="1" data-newposition="0">third-subchild
<span class="buttons-align">
<label class="switch">
<input class="sub-checkbox7" type="checkbox" id="user-10"
onclick="changeCategoryStatus(event.target, 10);"
>
<span class="slider round"></span>
</label>
</span>
<div class="move"><i class="fa fa-bars" aria-hidden="true"></i></div></li>
</ul>
</ul>
</div>
</div>
thanks for help.
The main issue with your current logic is that you are attaching the toggleCheck()
function to the main checkbox every time the checkbox is clicked. This causes the odd behaviour you see.
Also note that your HTML is invalid. li
elements must be children of the ul
only, not div
, and the ul
itself cannot be a child of another ul
. You need to structure your nested lists correctly. You can also improve the HTML by removing the incremental id and class attributes. They are an anti-pattern which leads to more complex code than necessary. Use DOM traversal to relate elements instead.
Regarding the JS code, you should avoid the use of the inline onclick
event handlers as they are no longer good practice. Use unobtrusive event handlers added via your JS logic. Also you're redefining the toggleCheck()
function numerous times, which is a big code smell.
With all that said, the HTML and JS can be massively simplified:
$('.sortable :checkbox').on('change', e => {
let $cb = $(e.target);
let isChecked = $cb.prop('checked');
$cb.closest('li').find(':checkbox').prop('checked', isChecked);
/*
// AJAX commented out for this demo only
$.ajax({
type: 'POST',
url: "{{url('admin/categories-status')}}",
data: {
id: $cb.prop('id'),
status: isChecked ? 'active' : 'inactive',
_token: "{{ csrf_token() }}"
},
success: function(result) {
$("#status-success").html(result.success).show();
setTimeout(function() {
$("#status-success").hide();
}, 3000);
}
});
*/
});
body {
/* background-color: #20262E; */
padding: 20px;
font-family: Helvetica;
}
.move {
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
<div class="sortable">
<ul class="group-caption">
<li class="main-parent category-sortable main-item" data-parent="4" data-position="4" data-newposition="1">
second room
<span class="buttons-align">
<label class="switch">
<input type="checkbox" id="4" />
<span class="slider round"></span>
</label>
</span>
<div class="move">
<i class="fa fa-bars" aria-hidden="true"></i>
</div>
<ul class="group-items group-items-parent">
<li class="group-item-parent category-sortable" data-parent="5" data-position="1" data-newposition="1">
second-child room
<span class="buttons-align">
<label class="switch">
<input type="checkbox" id="5" />
<span class="slider round"></span>
</label>
</span>
<div class="move">
<i class="fa fa-bars" aria-hidden="true"></i>
</div>
<ul class="group-items-child">
<li class="group-item-child category-sortable" data-parent="6" data-position="1" data-newposition="0">
second subchild
<span class="buttons-align">
<label class="switch">
<input type="checkbox" id="6" />
<span class="slider round"></span>
</label>
</span>
<div class="move"><i class="fa fa-bars" aria-hidden="true"></i></div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul class="group-caption">
<li class="main-parent category-sortable main-item" data-parent="7" data-position="4" data-newposition="2">
third-room
<span class="buttons-align">
<label class="switch">
<input type="checkbox" id="7" />
<span class="slider round"></span>
</label>
</span>
<div class="move">
<i class="fa fa-bars" aria-hidden="true"></i>
</div>
<ul class="group-items group-items-parent">
<li class="group-item-parent category-sortable" data-parent="9" data-position="1" data-newposition="1">
third-child
<span class="buttons-align">
<label class="switch">
<input type="checkbox" id="9" />
<span class="slider round"></span>
</label>
</span>
<div class="move">
<i class="fa fa-bars" aria-hidden="true"></i>
</div>
<ul class="group-items-child">
<li class="group-item-child category-sortable" data-parent="10" data-position="1" data-newposition="0">
third-subchild
<span class="buttons-align">
<label class="switch">
<input type="checkbox" id="10" />
<span class="slider round"></span>
</label>
</span>
<div class="move">
<i class="fa fa-bars" aria-hidden="true"></i>
</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>