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 class="theme-list-p"> <li> <span class="fa fa-plus switch-btn"></span> <input type="checkbox" name="" class="mt"> City <ul class="theme-list-c" style="display: none;"> <li><input type="checkbox" class="red" name=""> Bombay</li> <li><input type="checkbox" name=""> Delhi</li> <li><input type="checkbox" name=""> Agra</li> </ul> </li> <li><span class="fa fa-plus switch-btn"></span> <input type="checkbox" name=""> Colors <ul class="theme-list-c" 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>
Advertisement
Answer
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 class="theme-list-p"> <li> <span class="fa fa-plus switch-btn"></span> <input type="checkbox" name="" class="mt"> City <ul class="theme-list-c" style="display: none;"> <li><input type="checkbox" class="red" name=""> Bombay</li> <li><input type="checkbox" name=""> Delhi</li> <li><input type="checkbox" name=""> Agra</li> </ul> </li> <li><span class="fa fa-plus switch-btn"></span> <input type="checkbox" name=""> Colors <ul class="theme-list-c" 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.