KingCk
KingCk

Reputation: 153

Can we convert formArray data into comma separated string, Example at index 0:["1,3,4,6"]

Lets say i have a checkbox and each checkbox has a categoryId. When i check the checkbox i will get the categoryId and each data will be save as a formArray, example at index 0: 1,1:2,2:4,3:[6] . So this is the data i currently get but my question is instead of storing the data at different index number i want to get the result as index 0:["1,3,4,6"] as array of string. I want to store the data only in index 0 in other words i want to store all the checkbox categoryId only in one index as a string. I'll share my code below. This is the code that i used to get the categoryId from checkbox

onChange(categoryId: string[], isChecked: boolean) {
  debugger
  const categoryIdArray = (this.patientReportForm.controls.hubxCategoryId as FormArray);
  if (isChecked) {
    categoryIdArray.push(new FormControl(categoryId)) 
  } else {
    let index = categoryIdArray.controls.findIndex(x => x.value == categoryId)
    categoryIdArray.removeAt(index);
  }
}

This is formcontrol

this.patientReportForm = this.formBuilder.group({
      patientId : new FormControl(Number(this.clientId)),
      hubxCategoryId : this.formBuilder.array([]),
      notes : new FormControl(),
    })

this is my html section for checkbox

 <div *ngFor="let hubxReport of hubxReportList; let i=index">
                <div class="lineheader  "> 
                  <section class="" [formGroup]="patientReportForm">
                    <p><mat-checkbox color="primary" (change)="onChange(hubxReport.categoryId, $event.checked)">{{hubxReport.categoryName}}</mat-checkbox></p>
                  </section>
                </div>

this is the data i currently get current result

and this is the result i want to get expected result

my final result here patientid is null. Below i'm assigning patientid : this.clientid. when i debug and i check it, this.clientid carries a value 40.But when i submit patientid shows null

patientReportForm=this.getGroup({patientId : this.clientId ,hubxCategoryId:"",notes:""})

result

here this.clientid carries value 40. debug image

Upvotes: 0

Views: 260

Answers (2)

Eliseo
Eliseo

Reputation: 57939

  convertValue(){
    const values = this.form.get('hubxCategoryId').value;

    //values is an array [true,true,false,...]
    return this.hubxReport
            //filter gets [{hubxCategoryId:2,categoryName:".."},
            //             {hubxCategoryId:6,categoryName:".."},..]
           .filter((x, index) => values[index]) 

            //maps return only the "Id" [2,6,...]
           .map(x=>x.hubxCategoryId)
           
            //join return an string "2,6,..."
           .join(",")
  }

But take a look to this SO, you not create a FormArray else a FormControl that store an array

Update step by step

Imagine you has

hubxReportList=[{hubxCategoryId:1,categoryName:'Marka'}, 
                 {hubxCategoryId:2,categoryName:'Kilometraza'},
                 {hubxCategoryId:3,categoryName:'Alu felne'}]

You can to have a function like

  getGroup(data:any=null)
  {
    data=data || {patienID:0,hubxCategoryId :"",notes:""}
  
    const list=data.hubxCategoryId?data.hubxCategoryId.split(',').map(x=>+x):[]
    return new FormGroup({
      patienID:new FormControl<number>(data.patienID),
      hubxCategoryId :new FormArray(this.hubxReportList.map(x=>new FormControl(list.indexOf(x.hubxCategoryId)>0))),
      notes:new FormControl<string>(data.notes)
    }) 
  }

//and use 
patientReportForm2=this.getGroup(
             {patienID:0,hubxCategoryId:"1,3",notes:""})
//or 
patientReportForm2=this.getGroup()

As always we have a FormArray we use a getter

  get hubxCategoryIdArray()
  {
    return this.patientReportForm2.get('hubxCategoryId') as FormArray
  }

And the .html

<form [formGroup]="patientReportForm" (submit)="submit(patientReportForm)">
  <div class="lineheader" formArrayName="hubxCategoryId">
    <section
      class=""
      *ngFor="let control of hubxCategoryIdArray.controls; let i = index"
    >
      <p>
        <input type="checkbox" color="primary" [formControlName]="i" />
        {{ hubxReportList[i].categoryName }}
      </p>
    </section>
  </div>
  <button>submit</button>
</form>

The function submit like

  submit(form:FormGroup)
  {
    if (form.valid)
    {
      const data:any={...form.value};
      data.hubxCategoryId=this.hubxReportList
           .filter((x, index) => form.value.hubxCategoryId[index]) 
           .map(x=>x.hubxCategoryId)
           .join(",")

      console.log(data)
    }
  }

Another option is really use a FormControl, not a FormArray that store an string separated by commas

  getGroup(data:any=null)
  {
    data=data || {patienID:0,hubxCategoryId :"",notes:""}
  
    return new FormGroup({
      patienID:new FormControl(data.patienID),
      hubxCategoryId :new FormControl(data.hubxCategoryId ),
      notes:new FormControl(data.notes)
    })
  }

We use ngModel inside a FormGroup

<div *ngFor="let hubxReport of hubxReportList; let i = index">
  <div class="lineheader">
    <section class="">
      <p>
        <input
          type="checkbox"
          color="primary"
          [ngModel]="
            (patientReportForm.get('hubxCategoryId')?.value || [])
                .split(',').indexOf(
                    '' + hubxReport.hubxCategoryId
                 ) >= 0
             "
          (ngModelChange)="onChange(hubxReport.hubxCategoryId, $event)"
          [ngModelOptions]="{ standalone: true }"
        />
        {{ hubxReport.categoryName }}
      </p>
    </section>
  </div>
</div>

And the function onChange

 onChange(categoryId:any,checked:boolean)
  {
     let newValue:string
     const oldValue:string=this.patientReportForm.get('hubxCategoryId').value
     const oldArray=oldValue?oldValue.split(',').map(x=>+x):[] 
     if (checked)
     newValue=this.hubxReportList
              .filter((x) =>  x.hubxCategoryId==categoryId || oldArray.indexOf(x.hubxCategoryId)>=0) 
              .map(x=>x.hubxCategoryId)
              .join(",")     
  
      else
      newValue=this.hubxReportList
              .filter((x) =>  x.hubxCategoryId!=categoryId && oldArray.indexOf(x.hubxCategoryId)>=0) 
              .map(x=>x.hubxCategoryId)
              .join(",")     
  
              console.log(oldArray,newValue)

        this.patientReportForm.get('hubxCategoryId').setValue(newValue)
  }
  onChange(categoryId:any,checked:boolean)
  {
     let newValue:string
     const oldValue:string=this.patientReportForm.get('hubxCategoryId').value
     const oldArray=oldValue?oldValue.split(',').map(x=>+x):[] 
     if (checked)
     newValue=this.hubxReportList
              .filter((x) =>  x.hubxCategoryId==categoryId || oldArray.find(y=>y==x.hubxCategoryId)) 
              .map(x=>x.hubxCategoryId)
              .join(",")     
  
      else
      newValue=this.hubxReportList
              .filter((x) =>  x.hubxCategoryId!=categoryId && oldArray.find(y=>y==x.hubxCategoryId)) 
              .map(x=>x.hubxCategoryId)
              .join(",")     
  
        this.patientReportForm.get('hubxCategoryId').setValue(newValue)
  }

In this case we needn't make anything in submit

You can see in the stackblitz both case

BONUS: we can create a custom form control like the link I indicate, in this stackblitz is improve the code to mannage an string separated by commas

Upvotes: 2

Reaper
Reaper

Reputation: 412

Try this: let desiredFormat= this.patientReportForm.value.hubxCategoryId.join(",")

Upvotes: 0

Related Questions