Search code examples
angulartypescriptformshttpclientformarray

How to remove 'commas' while displaying the selected checkboxes in angular


form-page.component.html :

<h1>CAR SERVICE FORM</h1>

<form [formGroup]="form" (submit)="onSubmit()">
    <div>
        <label for="carmodel">Car Model:</label>
        <input type="text" class="form-control" formControlName="carmodel">
        <div *ngIf="form.controls['carmodel'].touched && form.controls['carmodel'].errors">
          <div *ngIf="form.controls['carmodel'].hasError('required')" class="error">Carmodel is required.</div>
          <div *ngIf="form.controls['carmodel'].hasError('minlength')">Carmodel should be minimum 3 characters.</div>
        </div>
    </div>

    <div>
        <label for="carnum">Car Number:</label>
        <input type="text" class="form-control" formControlName="carnum">
        <div *ngIf="form.controls['carnum'].touched && form.controls['carnum'].errors">
          <div *ngIf="form.controls['carnum'].hasError('required')" class="error">carnum is required.</div>
        </div>
      </div>



    <div>
        <label for="contactNumber">Contact Number:</label>
        <input type="text" class="form-control" formControlName="contactNumber">
        <div *ngIf="form.controls['contactNumber'].touched && form.controls['contactNumber'].errors">
          <div *ngIf="form.controls['contactNumber'].hasError('required')" class="error">Contact number is required.</div>
        </div>
    </div>
  
    <div>
      <label>Type of Service:</label>
      <div>
        <label><input type="radio" name="option" value="Waterwash" formControlName="option"> Waterwash </label>
      </div>
      <div>
        <label><input type="radio" name="option" value="Fullservice" formControlName="option"> Fullservice </label>
      </div>
      <div *ngIf="form.controls['option'].touched && form.controls['option'].invalid">
        <div class="error">Please select an option</div>
      </div>
    </div>
<div>
    <label>Addons:</label>
    <div *ngFor="let cbx of checkboxesFormArray.controls; let i = index">
      <label formArrayName="checkbox">
        <input type="checkbox" [formControlName]="i" (change)="checkedChanged($event)" [value]="checkboxes[i].value">
        {{checkboxes[i].name}}
      </label>
    </div>  
  </div>

    <div>
      <label>State:</label>
      <select formControlName="state" (change)="onStateChange()">
        <option *ngFor="let state of states" [value]="state">{{state}}</option>
      </select>
      <div *ngIf="form.controls['state'].touched && form.controls['state'].invalid">
        <div class="error">Please select a state</div>
      </div>
    </div>
 
    <div>
        <label>City:</label>
        <select formControlName="city">
            <option *ngFor="let city of cities[form.controls['state'].value]" [value]="city">{{city}}</option>
        </select>
        <div *ngIf="form.controls['city'].touched && form.controls['city'].invalid">
            <div class="error">Please select a city</div>
        </div>
    </div>

    <button type="submit" class="btn btn-primary">Submit</button>
    <button type="button" (click)="Reset()">Reset</button>
    <button (click)="goBack()">back</button>


    

</form>
<table>
    <thead>
      <tr>
        <th>Car Model</th>
        <th>Car Number</th>
        <th>Contact Number</th>
        <th>Type of Service</th>
        <th>Options</th>
        <th>State</th>
        <th>City</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let car of cars">
        <td>{{ car.carmodel }}</td>
        <td>{{ car.carnum }}</td>
        <td>{{ car.contactNumber }}</td>
        <td>{{ car.option }}</td>
        <td>{{ car.checkbox }}</td>
        <td>{{ car.state }}</td>
        <td>{{ car.city }}</td>
      </tr>
    </tbody>
  </table>

form-page.component.ts :

import { Component } from '@angular/core';
import { CommonModule, Location } from '@angular/common';
 
import { FormGroup, FormBuilder,FormControl, Validators, FormArray } from '@angular/forms';
 
import { CarServiceService } from 'src/app/services/car-service.service';
@Component({
  selector: 'app-form-page',
  templateUrl: './form-page.component.html',
  styleUrls: ['./form-page.component.css']
})
export class FormPageComponent {
//
  form: FormGroup;
  states: string[] = ['Tamilnadu', 'Kerala', 'Karnataka','Maharastra'];
  cities: {[key: string]: string[]} = {
    'Tamilnadu': ['Chennai', 'Coimbatore','Madurai'],
    'Kerala': ['Trivandrum','Kochi','Kollam'],
    'Karnataka': ['Bangalore', 'Mysore'],
    'Maharastra': ['Mumbai', 'Pune']
  };
  checkboxes = [
    { value: '10%off First service visit', name: '10%off First service visit' },
    { value: '10%off Waterwash', name: '10%off Waterwash' },
    { value: 'Free AC Inspection', name: 'Free AC Inspection' },
  ];
//  
  cars: any[] = [];
//
  checkboxValues: string[]=[];
//
 
  get checkboxesFormArray() {
    return this.form.controls['checkbox'] as FormArray;
  }
 
  constructor(private fb: FormBuilder,private location : Location,private carServiceService :CarServiceService) {
 
 
    this.form = this.fb.group({
      carmodel :['', [Validators.required, Validators.minLength(3)]],
      carnum :['', [Validators.required]],
      contactNumber: ['', [Validators.required, Validators.pattern(/^\d{10}$/)]],
      option: ['', Validators.required],
      checkbox: new FormArray([], Validators.required),
      state: ['', Validators.required],
      city: ['', Validators.required]
    });
    this.addCheckboxes();
  }
 
 
  addCheckboxes() {
    this.checkboxes.forEach(() =>
      this.checkboxesFormArray.push(new FormControl(''))
    );
  }
 
  goBack():void{
    this.location.back();
  }
 

  onSubmit() {
    if (this.form.valid) {
//      console.log(this.form.value);
 
 
      this.carServiceService.addCar(this.form.value).subscribe(response =>{
        console.log(response);
        this.carServiceService.getCars().subscribe(cars => {
          this.cars = cars; // Set the list of cars to the response data
          console.log(this.cars);
        });  
      });
 
    } else {
      // Form is invalid, display error messages
      this.form.markAllAsTouched();
    }
  }


 
 
  Reset(){
    this.form.reset();
  }
 
  onStateChange() {
    const state = this.form.controls['state'].value;
    this.form.controls['city'].setValue('');
    if (state) {
      this.form.controls['city'].enable();
    } else {
      this.form.controls['city'].disable();
    }
  }
  checkedChanged(e:any) {
    let index = this.checkboxes.findIndex(
      (item) => item.value === e.target.value
    );
    if (e.target.checked) {
      this.checkboxesFormArray.controls[index].setValue(e.target.value);
    } else {
      this.checkboxesFormArray.controls[index].setValue('');
    }
  }

 
}

also got this service named , car-service.service.ts:


import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Form } from '@angular/forms';

@Injectable({
  providedIn: 'root'
})
export class CarServiceService {

  constructor(private http: HttpClient) { }

  addCar(formData : any): Observable<any>{
    return this.http.post<any>('https://localhost:7095/api/Forms/submit-form',formData);
  }
  getCars(): Observable<any[]> {
    return this.http.get<any[]>('https://localhost:7095/api/Forms/get-forms');
  }
  
}

Im trying to post my input values of html form from angular to asp.net core web API and then getting those values back to print them below the html form in a table format. I'm able to post every fields and get back those values but there's a small thing that bothers me. In the checkbox field, If I selected the last two checkboxes, I get the values as

,10%off Waterwash,Free AC Inspection

and on selecting just the last checkbox, I get them like

,,Free AC Inspection

or on selecting the second checkbox alone, I get the values like,

,10%off Waterwash,

Basically I want to get rid of the comma in the form array. Can someone tell me how to do that


Solution

  • You need create an object removing the "empty" values of the array. So in submit function you can use

    onSubmit() {
        if (this.form.valid) {
          //create a new object
          const data={
            ...this.form.value, //<--all the value of your form
            checkbox:this.form.value.checkbox.filter(x=>x)
          }
          //send this object, not the form.value
          this.carServiceService.addCar(data).subscribe(response =>{
             ...
          }
     }
    

    But really the value of your checkboxesFormArray should be always an array with true or false, e.g. [true,true,false]

    As you want to pass to your API the value based in your array checkboxes the only you need are, in submit function, create a new object with the values of the form but the "checkbox property" changed

    onSubmit() {
        if (this.form.valid) {
          const data={
            ...this.form.value, //<--all the value of your form
            checkbox:this.form.value.checkbox
                 //will be,. e.g. [true,false,true]
                 .map((x:boolean,index:number)=>x?this.checkboxes[index].value:'')
                 //will be, e.g. ['10%off First service visit','','Free AC Inspection']
                 
                 .filter((x:string)=>x)
                 //will be,e.g. ['10%off First service visit','Free AC Inspection']
                 .join(',')
                 //will be '10%off First service visit,Free AC Inspection'
            }
    
         this.carServiceService.addCar(data).subscribe(response =>{
            ...
         }
    } 
    

    So we needn't use your function checkedChanged

    NOTE: I don't know if you want to send the array or a string separate by commas (remove the "join" if you need an array of string in your API.

    NOTE2: There're another approach that it's not use a FormArray else a simple FormControl, and use [(ngModel)] to change the FormControl. See this SO