Skip to content Skip to sidebar Skip to footer

Nested Parent/child Checkboxes - Working Solution Need Adjustment Help For Bootstrap

I have been looking for a 'complete' solution to nesting parent child checkboxes that change state correctly based on a hierarchy. Most 'solutions' do not work or only work to one

Solution 1:

Take a look at the free JSTree user control. It is JavaScript-based, open source and allows to be configured for multiple styles of tree views, for example:

enter image description here

Since the checkboxes displayed here are just images, you can replace them by radio buttons easily, and via event handling you can disallow multiple selections so they behave like radio buttons if required.

This is achieved by specifying the "checkbox" plugin as follows (see the snippet I provided below for the complete 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:

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

To get the checked values, use this function (assuming you have created a div with id="listForDisplay" as I did in the JSFiddle example):

var $listForDisplay = $("#listForDisplay");
function displayList(data) { // see: https://www.jstree.com/docs/events/var i, j, r = [];
    for (i = 0, j = data.selected.length; i < j; i++) {
        r.push(data.instance.get_node(data.selected[i]).text);
    }
    $listForDisplay.html('Selected: ' + r.join(', '));
}

This code can either be triggered in a click event or you can bind JSTree events like I did. Appending the following to the previous JavaScript snippet does the job:

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

Note: When a parent node is selected, the parent name is listed along with the childs. If only the childs are selected, the related parent(s) will not be listed.

You can find more about the options specifying the behaviour of this plugin here.


Runnable code snippet (complete code)

$(function() {

  var $demo1 = $("#demo1");
  
  var $listForDisplay = $("#listForDisplay");
  functiondisplayList(data) { // see: https://www.jstree.com/docs/events/var i, j, r = [];
    for (i = 0, j = data.selected.length; i < j; i++) {
      r.push(data.instance.get_node(data.selected[i]).text);
    }
    $listForDisplay.html('Selected: ' + r.join(', '));
  }

  $demo1.jstree({
    "themes": {
      "theme": "apple",
      "dots": false,
      "icons": false
    },
    "plugins": ["themes", "html_data", "checkbox", "sort", "ui"]
  });
  $demo1.on('loaded.jstree', function(e, data) {
    displayList(data);
  });
  $demo1.on('changed.jstree', function(e, data) {
    displayList(data);
  });
});
<head><scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><linkhref="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css"  /><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script></head><body><divid="demo1"class="demo"style="height:100px;"><ul><liid="phtml_1"><ahref="#">Root node 1</a><ul><liid="phtml_2"><ahref="#">Child node 1</a></li><liid="phtml_3"><ahref="#">Child node 2</a></li></ul></li><liid="phtml_4"><ahref="#">Root node 2</a></li></ul></div><br/><divid="listForDisplay" /></body>

Solution 2:

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
      });

      functioncheckSiblings(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 checkboxif (all && checked) {
              parentcheck.children('input[type="checkbox"]').prop({
                  indeterminate: false,
                  checked: checked
              });
              checkSiblings(parent);
          } elseif (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/

Post a Comment for "Nested Parent/child Checkboxes - Working Solution Need Adjustment Help For Bootstrap"