UIAPPDEVELOPER
UIAPPDEVELOPER

Reputation: 649

How to push array elements into object in angular 7

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"]}]*/
    }

    }

Upvotes: 0

Views: 1093

Answers (2)

TabsNotSpaces
TabsNotSpaces

Reputation: 1357

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

Upvotes: 1

Naga Sai A
Naga Sai A

Reputation: 10975

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

Upvotes: 0

Related Questions