Nested checkboxes with parent / child - working solution needs setup help for Bootstrap

I was looking for a “complete” solution for placing parent child checkboxes that correctly change state based on hierarchy.

Most “solutions” do not work or work only on one level. They also require that you check the boxes in a specific way.

This discussion covers the main points, but also provides a good solution, discovered by Rory here .

I tested it as part of my development project, and it works great autonomously. However, I use Bootstrap 2.x for checkboxes as well

I have a JSFiddle that shows a working example code, and then my version with the parent flag disabled, and then the version of the download code that does not work.

<!DOCTYPE html> <body> <!-- Raw working example from site http://css-tricks.com/indeterminate-checkboxes/ --> <b>Raw working example</b> <p> <ul> <li> <input type="checkbox" name="tall" id="tall"> <label for="tall">Tall Things</label> <ul> <li> <input type="checkbox" name="tall-1" id="tall-1"> <label for="tall-1">Buildings</label> </li> <li> <input type="checkbox" name="tall-2" id="tall-2"> <label for="tall-2">Giants</label> <ul> <li> <input type="checkbox" name="tall-2-1" id="tall-2-1"> <label for="tall-2-1">Andre</label> </li> <li> <input type="checkbox" name="tall-2-2" id="tall-2-2"> <label for="tall-2-2">Paul Bunyan</label> <ul> <li> <input type="checkbox" name="tall-2-2-1" id="tall-2-2-1"> <label for="tall-2-2-1">Son</label> </li> <li> <input type="checkbox" name="tall-2-2-2" id="tall-2-2-2"> <label for="tall-2-2-2">Daughter</label> </li> </ul> </li> </ul> </li> <li> <input type="checkbox" name="tall-3" id="tall-3"> <label for="tall-3">Two sandwiches</label> </li> </ul> </li> <li> <input type="checkbox" name="short" id="short"> <label for="short">Short Things</label> <ul> <li> <input type="checkbox" name="short-1" id="short-1"> <label for="short-1">Smurfs</label> </li> <li> <input type="checkbox" name="short-2" id="short-2"> <label for="short-2">Mushrooms</label> </li> <li> <input type="checkbox" name="short-3" id="short-3"> <label for="short-3">One Sandwich</label> </li> </ul> </li> </ul> <hr> <!-- Non Bootstrap Example --> <b>My initial code example - Is Working</b> <p> <ul> <li> <input type="checkbox" name="" value="" disabled><strong>Ford</strong> <ul> <li> <input type="checkbox" name="" value="">Fiesta</label> </li> <li> <input type="checkbox" name="" value="">Focus</label> </li> <li> <input type="checkbox" name="" value="">Mondeo</label> </li> </ul> </li> <li> <input type="checkbox" name="" value="" disabled><strong>Vauxhall</strong> <ul> <li> <input type="checkbox" name="" value="">Corsa</label> </li> <li> <input type="checkbox" name="" value="">Astra</label> </li> <li> <input type="checkbox" name="" value="">Vectra</label> </li> </ul> </li> </ul> <hr> <!-- Bootstrap Example --> <b>Bootstrap based code example - Not Working</b> <p> <ul> <li> <label class="checkbox"> <input type="checkbox" name="" value="" disabled><strong>Ford</strong> </label> <ul> <li> <label class="checkbox"> <input type="checkbox" name="" value="">Fiesta</label> </li> <li> <label class="checkbox"> <input type="checkbox" name="" value="">Focus</label> </li> <li> <label class="checkbox"> <input type="checkbox" name="" value="">Mondeo</label> </li> </ul> </li> <li> <label class="checkbox"> <input type="checkbox" name="" value="" disabled><strong>Vauxhall</strong> </label> <ul> <li> <label class="checkbox"> <input type="checkbox" name="" value="">Corsa</label> </li> <li> <label class="checkbox"> <input type="checkbox" name="" value="">Astra</label> </li> <li> <label class="checkbox"> <input type="checkbox" name="" value="">Vectra</label> </li> </ul> </li> </ul> 
 $(function () { // Apparently click is better chan change? Cuz IE? $('input[type="checkbox"]').change(function (e) { var checked = $(this).prop("checked"), container = $(this).parent(), siblings = container.siblings(); container.find('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); function checkSiblings(el) { var parent = el.parent().parent(), all = true; el.siblings().each(function () { return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked); }); if (all && checked) { parent.children('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); checkSiblings(parent); } else if (all && !checked) { parent.children('input[type="checkbox"]').prop("checked", checked); parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0)); checkSiblings(parent); } else { el.parents("li").children('input[type="checkbox"]').prop({ indeterminate: true, checked: false }); } } checkSiblings(container); }); }); 

I understand that the code needs to be changed somewhere in order to use the parents or the nearest one . Maybe someone who is much better than the code can help determine where the change should occur in order to get the Bootstrap version.

+7
javascript jquery checkbox twitter-bootstrap parent-child
source share
2 answers

Take a look at the free JSTree user control. It is based on JavaScript, open source and allows you to customize several styles of tree views, for example:

enter image description here

Since the checkboxes displayed here are just images, you can easily replace them using the radio buttons, and when processing events, you can prohibit multiple selections so that they behave like switches, if necessary.

This is achieved by specifying the "checkbox" plugin as follows (see JSFiddle I presented the full working code):

 $(function () { $("#demo1") .jstree({ "themes": { "theme": "apple","dots": false,"icons": false }, "plugins": ["themes", "html_data", "checkbox", "sort", "ui"] }); }); 

The corresponding HTML structure looks like this: just include it in the body of your page:

 <div id="demo1" class="demo" style="height:100px;"> <ul> <li id="phtml_1"> <a href="#">Root node 1</a> <ul> <li id="phtml_2"> <a href="#">Child node 1</a> </li> <li id="phtml_3"> <a href="#">Child node 2</a> </li> </ul> </li> <li id="phtml_4"> <a href="#">Root node 2</a> </li> </ul> </div> 

To get checked values, use this function (if you created a div with id="listForDisplay" , as it was in the JSFiddle example):

  function displayList() { var result=$("#listForDisplay"); var checked = $("#demo1").jstree("get_checked", null, true); var selectedNodes=""; result.text(selectedNodes); $(checked).each(function (i, node) { var id = $(node).attr("id"); var text = $("#"+id).text(); var parentId = $(node).attr("parentId"); alert(parentId); alert(id); if (selectedNodes!=="") selectedNodes+=","; selectedNodes+=text; }); result.text(selectedNodes); } 

This code can be fired in a click event, or you can bind JSTree events like me. Adding the following to the previous JavaScript snippet does the job:

  $("#demo1") .bind('loaded.jstree', function (e, data) { displayList(); }) .bind('change_state.jstree', function (e, data) { displayList(); }); 

The only problem is that displayList() seems to create duplicate entries when the entire parent is selected (which means that the parent names are specified along with the children).

Read more about the parameters that determine the behavior of this plugin here .

+3
source share

you can try something like this

  $(function () { $('input[type="checkbox"]').change(function (e) { var checked = $(this).prop("checked"), container = $(this).closest("li"),//get closest li instead of parent siblings = container.siblings(); container.find('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); function checkSiblings(el) { var parent = el.parent().parent(), all = true, parentcheck=parent.children("label");//get the label that contains the disabled checkbox el.siblings().each(function () { return all = ($(this).find('input[type="checkbox"]').prop("checked") === checked); }); //use parentcheck instead of parent to get the children checkbox if (all && checked) { parentcheck.children('input[type="checkbox"]').prop({ indeterminate: false, checked: checked }); checkSiblings(parent); } else if (all && !checked) { parentcheck.children('input[type="checkbox"]').prop("checked", checked); parentcheck.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0)); checkSiblings(parent); } else { parentcheck.children('input[type="checkbox"]').prop({ indeterminate: true, checked: false }); } } checkSiblings(container); }); }); 

http://jsfiddle.net/Mvs87/2/

+3
source share

All Articles