Problem setting indeterminate value of parent checkbox in group

356 views Asked by At

I have a JSON file with hierarchical data:

[
  {
    "id": 0,
    "label": "Gap Inc.",
    "value": "Gap Inc",
    "checked": false,
    "children": [
      {
        "id": 0,
        "label": "Banana Republic",
        "value": "Banana Republic",
        "checked": false
      },
      {
        "id": 1,
        "label": "Gap",
        "value": "Gap ",
        "checked": false
      },
      {
        "id": 2,
        "label": "Hill City",
        "value": "Hill City",
        "checked": false
      },
      {
        "id": 3,
        "label": "Old Navy",
        "value": "Old Navy",
        "checked": false
      }
    ]
  },
  {
    "id": 1,
    "label": "Home Depot",
    "value": "Home Depot",
    "checked": false,
    "children": []
  },
  {
    "id": 2,
    "label": "TJX",
    "value": "TJX Companies",
    "checked": false,
    "children": [
      {
        "id": 0,
        "label": "TJ Maxx",
        "value": "TJ Maxx ",
        "checked": false
      },
      {
        "id": 1,
        "label": "Marshalls",
        "value": "Marshalls",
        "checked": false
      },
      {
        "id": 2,
        "label": "Home Goods",
        "value": "Home Goods",
        "checked": false
      }
    ]
  }
]

I am using it to create a set of nested HTML lists with checkboxes:

<ul class="list-unstyled">
  <li *ngFor="let parent of accountList; let q = index">
     <div class="form-check">
         <input id="parent-{{q}}"
                class="form-check-input"
                type="checkbox"
                [(ngModel)]="parent.checked"
                (click)="selectChildren(parent, $event)"
                [indeterminate]="selectedChildren.length">
         <label for="parent-item" class="form-check-label">
           {{parent.label}}
         </label>
     </div>

     <ul class="list-unstyled pl-4">
         <li *ngFor="let child of parent.children; let i = index;">
             <div class="form-check">
                  <input id="child-{{i}}"
                         class="form-check-input"
                         type="checkbox"
                         [(ngModel)]="child.checked"
                         (click)="selectChild(child, $event)">
                  <label for="child-{{i}}" class="form-check-label">
                       {{child.label}}
                   </label>
             </div>
         </li>
     </ul>
   </li>
</ul>

What's supposed to happen

If you click a parent checkbox, it checks all the children. If you click only one child, its parent is set to indeterminate.

What DOES happen

If you click a parent checkbox, it checks all the children. If you click only one child, ALL parents are set to indeterminate.

I assume I screwed up something somewhere. I think I have mapped the indeterminate attribute to the length of any selected children (here selectedChildren instead of only the children of the given parent. Not sure how to fix that...

Here is the typescript:

selectedChildren = [];

selectChildren = function(data, event) {
    const parentChecked = !data.checked;
    data.children.forEach((child, key2) => {
      child.checked = parentChecked;
    });
  };

  selectChild = (data, event) => {
    if (this.selectedChildren.indexOf(data.id) === -1) {
      this.selectedChildren.push(data.id);
      data.checked = true;
    } else {
      this.selectedChildren.splice(this.selectedChildren.indexOf(data.id), 1);
      data.checked = false;
    }
  };
0

There are 0 answers