0

I have some checkboxes whose value coming from json using ngFor. When I select those checkboxes and click submit, I need to capture the 'li' tag value and selected checkbox value in the form of array of object mentioned in output in code section. Here I am getting only 'li' tag value/text in the array but I am not getting how to push it into object along with selected checkbox value like output format.Here is the code below.

home.component.html

 <div class="col-md-3" id="leftNavBar">
      <ul *ngFor="let item of nestedjson">
        <li class="parentNav">{{item.name}}</li>
        <li class="childData">
          <ul>
            <li *ngFor="let child of item.value">{{child}}<span class="pull-right"><input type="checkbox"></span></li>
          </ul>
        </li>
      </ul>
      <div><button type="submit" (click)="getit()">submit</button></div>
    </div>

home.component.ts

  import { Component, OnInit } from '@angular/core';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    import Speech from 'speak-tts';
     import { RxSpeechRecognitionService, resultList, } from '@kamiazya/ngx-speech-recognition';
    @Component({
      selector: 'app-home',
      templateUrl: './home.component.html',
      styleUrls: ['./home.component.css'],

      providers: [ RxSpeechRecognitionService ]
    })
    export class HomeComponent implements OnInit { 
        data:any;
        nestedjson:any;
        message = '';
        test:any;
     constructor(private formBuilder: FormBuilder,public service: RxSpeechRecognitionService) {
         }

      ngOnInit() {
         this.nestedjson = [
        { name: "parent1", value: ["child11", "child12"] },
        { name: "parent2", value: ["child2"] },
        { name: "parent3", value: ["child3"] }
      ];
    } 

    getit(){
        const data = this.nestedjson;
        let duplicatePushArray = [];
    for(let i = 0; i < data.length ; i++){
      if(duplicatePushArray.indexOf(data[i].name) === -1) {
        duplicatePushArray.push(data[i].name);
      } else {
        console.log(`${data[i]} is already pushed into array`);
      }
    }    
    console.log('Final Array: ', duplicatePushArray)
   /*output: [{"name":"parent1","value":["child11","child12"]},{"name":"parent2","value":["child2"]},{"name":"parent3","value":["child3"]}]*/
    }

    }
6
  • is that ouput after checking all checkboxes ?? please share some scenarios and expected output Commented Nov 5, 2019 at 19:21
  • Output format is there already in the 'home.component.ts' commented code. I need to get output once you select the checkboxes and click submit only Commented Nov 5, 2019 at 19:33
  • output- [{"name":"parent1","value":["child11","child12"]},{"name":"parent2","value":["child2"]},{"name":"parent3","value":["child3"]}] Commented Nov 5, 2019 at 19:41
  • @UIAPIDEVELOPER, if only child11 is selected, do you expect both values - from parent 1 - {"name":"parent1","value":["child11","child12"] or just only child11 - {"name":"parent1","value":["child11"] Commented Nov 5, 2019 at 19:43
  • {"name":"parent1","value":["child11","child12"]} Commented Nov 5, 2019 at 19:47

2 Answers 2

1

You don't have anything happening when the checkbox is selected. I would recommending adding an onChange binding so that you can save all of your checked children to an array that you can reference when you click submit.

home.component.html

  <li *ngFor="let child of item.value">{{child}}
    <span class="pull-right">
      <input type="checkbox" (change)="addtoChecked(child)">
    </span>
  </li>

home.component.ts

private checkedChildren = <string[]>[];
public addToChecked(child: string): void {
  if(this.checkedChildren.indexOf(child) > -1){ // you can also pass in the $event from the html to this method to determine if it was checked or not
    this.checkedChildren = this.checkedChildren.filter(c => c !== child);
  } else {
    this.checkedChildren.push(child);
  }
}

getit(): void {
  const output = <{name: string, value: string[]}[]>[];
  this.checkedChildren.forEach((child) => {
    const jsonData = this.nestedjson.find(j => j.value.indexOf(child) > -1);
    if(!jsonData) {
      // something went wrong
      return;
    }

    const existingDataIndex = output.findIndex(o => o.name == jsonData.name);
    if(existingDataIndex === -1){
      output.push({ name: jsonData.name, value: [child]});
    } else {
      output[existingDataIndex].value.push(child);
    }
  });
  console.log(output);
}

Sign up to request clarification or add additional context in comments.

7 Comments

I am getting only checked value after selecting checkbox into array format, but how to combine with 'li' tag value and put it with array of object like output- [{"name":"parent1","value":["child11","child12"]},{"name":"parent2","value":["child2"]},{"name":"parent3","value":["child3"]}]
updated answer. is that more of what you're looking for? If the child was selected, the parent object will be added to the output
updated again based on comments to question. Only the selected children will get returned with the parent objects
Thanks one issue is there suppose if I select only 'child1' its showing child1,child2 both like {"name":"parent1","value":["child11","child12"]} , it should show only selected child
After using updated answer getting error on this line output.push({ name: jsonData.name, value[child]}); "No value exists in scope for shorthand property value either declare one or provide initialiser"
|
0

To achieve expected result, use below option of using reduce and checked flags for checkboxes

  1. Add checked array to original Array to keep track of checked boxes

    this.nestedjson.forEach(v => v.checked = Array(v.value.length).fill(false));

  2. Updated array of checked values based on checked checkboxes

  3. Using reduce updated Final array by filtering out only checked boxes

let duplicatePushArray = this.nestedjson.reduce((acc, v) => { let temp = {name: v.name, value: []}; v.checked.forEach((val, i) => { if(val){ temp.value.push(v.value[i]); } }) if(temp.value.length > 0){ acc.push(temp) } return acc }, []);

Updated app.component.html and app.component.ts files below for reference

app.component.html:

<div class="col-md-3" id="leftNavBar">
      <ul *ngFor="let item of nestedjson">
        <li class="parentNav">{{item.name}}</li>
        <li class="childData">
          <ul>
            <li *ngFor="let child of item.value; let i = index">{{child}}<span class="pull-right"><input type="checkbox" (change)="item.checked[i] = !item.checked[i]"></span></li>
          </ul>
        </li>
      </ul>
      <div><button type="submit" (click)="getit()">submit</button></div>
    </div>

app.component.ts:

import { Component, OnInit } from '@angular/core';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    @Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
      })
    export class AppComponent implements OnInit { 
        data:any;
        nestedjson:any;
        message = '';
        test:any;
     constructor(private formBuilder: FormBuilder) {
         }

      ngOnInit() {
         this.nestedjson = [
        { name: "parent1", value: ["child11", "child12"] },
        { name: "parent2", value: ["child2"] },
        { name: "parent3", value: ["child3"] }
      ];

      this.nestedjson.forEach(v => v.checked = Array(v.value.length).fill(false));
    } 

    getit(){
        const data = this.nestedjson;
        let duplicatePushArray = this.nestedjson.reduce((acc, v) => {
          let temp = {name: v.name, value: []};
          v.checked.forEach((val, i) => {
            if(val){
                temp.value.push(v.value[i]);
            }
          })
          if(temp.value.length > 0){
                acc.push(temp)
          }
          return acc
        }, []);

    console.log('Final Array: ', duplicatePushArray)
   /*output: [{"name":"parent1","value":["child11","child12"]},{"name":"parent2","value":["child2"]},{"name":"parent3","value":["child3"]}]*/
    }
    }

Sample working code for reference - https://stackblitz.com/edit/angular-b9fmyz?file=src/app/app.component.html

3 Comments

Thanks for your answer,I implemented in my project its working fine but in case of radio box if I check and uncheck it and check again other radio box(in case of parent1), and click submit button , Its showing into true for both in the checked value console.log(data) ,It not working like checkbox. I mean checked status is not coming properly, here is the modificaion <li *ngFor="let child of item.value; let i = index">{{child}}<span class="pull-right"><input name="{{item.name}}" value="{{child}}" type="radio" (change)="item.checked[i] = !item.checked[i]"></span></li>
@UIAPPDEVELOPER, so it is working fine for checkboxes and failing with radio button?
Can you please help me on it,Here my main concern to capture the checked values on submit, not on change or on select,Also I am getting empty array when my checkboxes are pre selected

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.