Hello, I'm creating a select all functionality by check box, When we check one checkbox (City) it selects all checkboxes (Bombay, Delhi, Agra) of its child ul. And when uncheck a checkbox (City) it unchecks all checkboxes (Bombay, Delhi, Agra).
Now I need to add the "indeterminate" stage also. when the user uncheck any checkbox (Bombay, Delhi, Agra). It should add "indeterminate" stage in parent checkbox (City). How to achieve this, Kindly check the image for better understanding.
HTML
<ul >
<li>
<span ></span> <input type="checkbox" name="" > City
<ul style="display: none;">
<li><input type="checkbox" name=""> Bombay</li>
<li><input type="checkbox" name=""> Delhi</li>
<li><input type="checkbox" name=""> Agra</li>
</ul>
</li>
<li><span ></span> <input type="checkbox" name=""> Colors
<ul style="display: none;">
<li><input type="checkbox" name=""> Red</li>
<li><input type="checkbox" name=""> Green</li>
<li><input type="checkbox" name=""> Blue</li>
</ul>
</li>
</ul>
jquery
<script type="text/javascript">
$(document).on('change', '.theme-list-p li input', function() {
if($('.theme-list-c li input').is(':checked')){
$(this).parent('li input').prop('indeterminate', $(this).prop("checked"));
}
$(this).next('.theme-list-c').find('li input').prop('checked', $(this).prop("checked"));
});
$(document).on('click', '.switch-btn', function(){
$(this).toggleClass('fa-minus')
$(this).closest("li").find(".theme-list-c").toggle()
});
</script>
CodePudding user response:
Consider the following.
$(function() {
$(document).on('change', '.theme-list-p li input', function() {
var prop = $(this).prop("checked");
if ($(this).closest("ul").hasClass("theme-list-p")) {
// Select & De-select All Scenario - Top Level
console.log("Select All", prop);
$(this).next("ul").find("li > input").prop("checked", prop);
} else {
// Child Selected
console.log("Select Child", prop);
if ($(this).closest("ul").find("input:checked").length == $(this).closest("ul").find("input").length) {
// Match All case
$(this).closest("ul").parent().find("> input").prop({
checked: true,
indeterminate: false
});
} else if ($(this).closest("ul").find("input:checked").length > 0) {
// Match one or more, not all
$(this).closest("ul").parent().find("> input").prop("indeterminate", true);
} else {
// Match None
$(this).closest("ul").parent().find("> input").prop({
checked: false,
indeterminate: false
});
}
}
});
$(document).on('click', '.switch-btn', function() {
$(this).toggleClass('fa-minus')
$(this).closest("li").find(".theme-list-c").toggle()
});
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul >
<li>
<span ></span> <input type="checkbox" name="" > City
<ul style="display: none;">
<li><input type="checkbox" name=""> Bombay</li>
<li><input type="checkbox" name=""> Delhi</li>
<li><input type="checkbox" name=""> Agra</li>
</ul>
</li>
<li><span ></span> <input type="checkbox" name=""> Colors
<ul style="display: none;">
<li><input type="checkbox" name=""> Red</li>
<li><input type="checkbox" name=""> Green</li>
<li><input type="checkbox" name=""> Blue</li>
</ul>
</li>
</ul>
Please see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#indeterminate_state_checkboxes
In your code, you were targeting with .parent()
and when when click
was on a child element, of a list, that was a child of another list, you did not get the expected results.
Your logic also did not allow for multiple selection or if the selection is All or None. This code accounts for all these scenarios.