Tips for implementing checkboxes for parents and children using Angular and Bootstrap version 3.3.7

My specific requirement is as follows:

Whenever the parent element is clicked, its child elements should also be selected. It should also be possible to deselect any undesired elements. Upon button click, the selected parent and children names should be obtained as an object.

What I have done so far:

I have created a list of parents and children, provided checkboxes for the parents, and retrieved the parents' values after checking and unchecking them.

I am currently stuck on how to select the children within that parent and retrieve the values of both the parent and children.

Below is my code snippet:

.ts

@ViewChildren('myItem') item;
selectedIds = [];
display: any;
data: any;

ngOnInit(){
    // dynamic JSON 
    this.data = {
        "info": {
             "laptop": {},
             "config": {
                  "properties": {
                       "ram": {},
                       "processor": {},
                       "hdd": {}
                   }
              },
              "link": {},
               "name": {},
               "company": {
                    "properties": {
                         "model": {},
                         "maker": {"type": "integer"},
                         "country": {"type": "text"},
                         "enterprise": {}
                     }
                }
          }
    };

    this.display = this.data['info'];
    console.log(this.display);
}

change(data, event){
     if (event.target.checked === true) {
          this.selectedIds.push({id: data, checked: event.target.checked});
          console.log('Selected data ', JSON.stringify(this.selectedIds));
     }
     if (event.target.checked === false) {
          this.selectedIds = this.selectedIds.filter((item) => item.id !== data);
     }
}

getData(){
      const filtered = this.selectedIds.filter(item => item.id)
      console.log(JSON.stringify(filtered));
}

.html code

<ul class="list-group" *ngFor="let parent of display | keyvalue">
  <li class="list-group-item">  
       <input type="checkbox" [value]="parent.key" [(ngModel)]="parent.check" #myItem (change)="change(parent.key, $event)">{{parent.key}}
   </li>
   <ng-container *ngIf="parent.check && parent.value.hasOwnProperty('properties')">
         <ul *ngFor="let child of parent.value.properties | keyvalue">
              <li>
                 {{child.key}}
              </li>
         </ul>  
   </ng-container> 
</ul>

<hr>

<button class="btn btn-primary" (click)="getData()">Get Data</button>

My StackBlitz link

https://stackblitz.com/edit/angular-8vqwsc

https://i.sstatic.net/Sker2.png

Answer №1

Just pass the "children" to your function as the only requirement

(change)="change(parent.key,parent.value.properties,$event)"

Your function should look like this after passing children

  change(data, children, event) {
    if (event.target.checked === true) {
      this.selectedIds.push({ id: data, checked: event.target.checked });
      for (let child in children) {
        this.selectedIds.push({ id: child, checked: event.target.checked });
      }
    }
    if (event.target.checked === false) {
      this.selectedIds = this.selectedIds.filter((item) => item.id !== data);
      for (let child in children) {
        this.selectedIds = this.selectedIds.filter((item) => item.id !== child);
      }
    }

A problem arises when displaying selected values. To fix this, create a new function:

  isChecked(child) {
    let item = this.selectedIds.find(x => x.id == child.key)
    return item ? item.checked : false
  }

Add a (click) event to the "children" to update the selection

  <ul *ngFor="let child of parent.value.properties | keyvalue">
  <li>
    <input  type="checkbox" [checked]="isChecked(child)" (change)="change(child.key,null,$event)"/>
    {{child.key}}
  </li>
  </ul>  

An alternative method involves restructuring your data like this:

this.data2 =[ 
  {
    "id":"laptop","checked":false
    },
    {"id":"config","checked":false,"properties": [
        {"id":"ram","checked":false},
        {"id":"processor","checked":false},
        {"id":"ram","checked":false}
      ]
    },
    // Rest of the data entries here ...
]

Update your HTML accordingly:

<ul *ngFor="let parent of data2">
  <li><input  type="checkbox" [(ngModel)]="parent.checked" (change)="changedChild(parent.checked,parent.properties)"> {{parent.id}}
      <ng-container *ngIf="parent.checked">
        <ul  *ngFor="let child of parent.properties">
      <li>
        <input  type="checkbox" [(ngModel)]="child.checked" />
        {{child.id}}
      </li>
      </ul>  
      </ng-container>
  </li>
</ul>

Function for handling changes:

changedChild(value,children)
{
   if (children)
       children.forEach(x=>x.checked=value)
}

Updated adding object to this.selectedChild the functions becomes

function updates with explanation goes here...

And the html

html code that is updated goes here...

See forked stackblitz

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Display the current position of the caret in a field that cannot be edited

Can a virtual caret be displayed between two letter boundaries in HTML/CSS/JavaScript, for example in a regular div without using contenteditable=true? Imagine having the following: <div>Hello world</div> If I were to click between the "w" a ...

Incorporating a remote PHP file into your website using JavaScript

Is it feasible to utilize JS (jQuery) for executing a $.post from any website on any domain to a script on my server? This query stems from my reluctance to disclose my PHP files to clients (and avoid spending money on ionCube or similar solutions). By se ...

How to eliminate the top spacing in a Bootstrap 4 navbar

I'm facing an issue with the bootstrap 4 navbar - I am trying to get rid of the white space that appears above the nav bar but so far, my attempts have been unsuccessful. Here's how it looks when rendered: https://i.sstatic.net/zfyWJ.jpg It see ...

jQuery Animated List - Nested items are unresponsive to clicks

Looking to create a dynamic nested list using jQuery for animations, but unsure of the best approach. Currently, I'm adjusting the length of the parent list item and revealing the nested items. The issue is that the parent item's length covers ...

Encountering a 401 error when trying to access OneNote resource in Angular 5 with Microsoft Graph

I have encountered an issue while trying to request resources from Microsoft graph (for OneNote API). My concern revolves around the correct method of obtaining an access token. I am utilizing the implicit flow for my Angular 5 frontend application. The p ...

What are the advantages of combining a library (using Rollup or Webpack) instead of simply transpiling it with Babel?

When developing a library in JavaScript, what are the benefits of using tools like Rollup or Webpack for bundling rather than just transpiling with Babel? One potential advantage could be that by bundling, you ensure that your dependencies are packaged eff ...

Maintaining the user interface state while utilizing $resources in AngularJS

For my app, users have the ability to create and delete items. I've implemented $resources for this functionality, which is working really well. However, I'd like to implement a loading screen that appears whenever a request is being processed. ...

Loading a div using Ajax within a frame

My php page includes a div that is supposed to be populated by an Ajax call. function showcopay() { var apa = document.getElementById("alert_id").value; $("#copay").load('show_copay.php?pid='+apa); } The parent page of the div used to be ...

Is it incorrect to append an array to a ul block using jQuery?

I am encountering an issue when trying to append an array to HTML. The array consists of HTML elements, starting with "li", then "img", and ending with "/li". When I try to append the array, it returns: <li></li> <img src="..."> Howeve ...

What is the best way to set checkboxes to default values using a model?

My journey with angular.js continues as I embark on creating my first non-tutorial web app. In this endeavor, I am utilizing two smart-tables and checklist-model for a seamless user experience. The initial table uses a st-safe-src of all_types, containing ...

What is the recommended way to define a recursive TypeScript object that consists of keys that are exclusively strings?

I am seeking to define a type for an arbitrary object with only string keys (excluding symbol) at each level of nesting. Here is what I envision (though the example provided does not work and is not valid): type RecursiveRecord = { [key: string]: ...

Adjusting Modal Size Dynamically Based on Browser Screen Resolution Changes

Working on a jQuery simple modal that loads on load and closes after 15 seconds. The issue I'm facing is when the user's browser screen resolution changes, the size of the modal varies if width and height are set. I attempted to capture the user& ...

The assigned type 'string' for Apache ECharts does not match the expected type 'pictorialBar'

This demonstration is functional. Nevertheless, the options utilize any and my goal is to convert them to the EChartOption type. This is my current progress and the demonstration compiles successfully with this setup (With type: 'bar' commented ...

What are the steps to resolving an issue with importing a css file in next.js?

Error: ./node_modules/quill-emoji/dist/quill-emoji.css ModuleParseError: Module parse failed: Unexpected character '�' (1:0) You may need a suitable loader for handling this file type, as there are currently no configured loaders to process it. ...

Adjusting the OrbitControl target in a React environment

I attempted to create a model using react-three-fiber and react-drei, but the OrbitControl target setting is causing it to appear too high. import React, { useRef, useState, Suspense, useEffect } from 'react' import { Canvas, useFrame, useLoader, ...

What is the best approach for addressing null values within my sorting function?

I created a React table with sortable headers for ascending and descending values. It works by converting string values to numbers for sorting. However, my numeric(x) function encounters an issue when it comes across a null value in my dataset. This is th ...

When running npm install in an Angular project, a Node error occurs due to cb() not being called within npm ERR!

I encountered an issue when I cloned a Git Angular 11 project and ran npm install. The error message displayed was as follows: npm WARN deprecated <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dda9aeb1b4b3a99debf3ecf3ee">[e ...

Loading GLTF model via XHR may take an infinite amount of time to reach full completion

I am attempting to load a GLTF model of a piano using XHR and showcase the loading progress on a webpage. The model is being loaded utilizing the Three.js library. On a local server, everything works perfectly - the loading percentage is shown accurately, ...

Utilizing various APIs with distinct Authentication headers concurrently within an Angular JS application

Hey there, I'm new to AngularJs and could really use some advice or help from you guys! I'm working on an app that allows users to login and check their current location in a building using the Cisco CMX server. This server calculates the user&a ...

Utilize the 'response.download' method to retrieve unique data not typically expected for a given request

Each time I try to download a file, the response I get is different. The file is generated correctly every time: user,first_name,last_name,active,completed_training 4,Foo,Bas,YES,YES 5,Ble,Loco,NO,NO 9,gui2,md,NO,NO 3137,foo,baz,NO,NO However, the respons ...