skip to Main Content

I’ve created a component "form-page" in the "form" module:

form-page.component.html:

<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>
        <label><input type="checkbox" value="10%off First service visit" formControlName="checkbox"> 10%off First service visit</label>
      </div>
      <div>
        <label><input type="checkbox" value="10%off Waterwash" formControlName="checkbox"> 10%off Waterwash</label>
      </div>
      <div>
        <label><input type="checkbox" value="Free AC Inspection" formControlName="checkbox"> Free AC Inspection</label>
      </div>
      <div *ngIf="form.controls['checkbox'].touched && form.controls['checkbox'].invalid">
        <div class="error">Please select at least one Addon</div>
      </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>

form-page.component.ts:

import { Component } from '@angular/core';
import { Location } from '@angular/common';
//
import { FormGroup, FormBuilder, Validators } 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']
  };
  

  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: ['', Validators.required],
      state: ['', Validators.required],
      city: ['', Validators.required]
    });
  }

  goBack():void{
    this.location.back();
  }

  

  onSubmit() {
    if (this.form.valid) {
      this.carServiceService.addCar(this.form.value).subscribe(response =>{
        console.log(response);
      });

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

Created a service named "car-service" to POST:

car-service.service.ts:

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

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

I’m trying to post the form values to the API. When I click on submit I get an error 400.

POST https://localhost:7095/api/Forms/submit-form 400

Error:

ERROR HttpErrorResponse {headers: HttpHeaders, status: 400, statusText: 'OK', url: 'https://localhost:7095/api/Forms/submit-form', ok: false, …}error: {type: 'https://tools.ietf.org/html/rfc7231#section-6.5.1', title: 'One or more validation errors occurred.', status: 400, traceId: '00-88c37085e17ce434f174cf65d020c28e-1bd09d34125cb2dc-00', errors: {…}}headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}message: "Http failure response for https://localhost:7095/api/Forms/submit-form: 400 OK"name: "HttpErrorResponse"ok: falsestatus: 400statusText: "OK"url: "https://localhost:7095/api/Forms/submit-form"[[Prototype]]: 

In asp.net-core web API:

FormData.cs:

namespace AngularApi.Model
{
    public class FormData
    {
        public string Carmodel { get; set; }
        public string Carnum { get; set; }
        public string ContactNumber { get; set; }
        public string Option { get; set; }
        public List<string> Checkbox { get; set; }
        public string State { get; set; }
        public string City { get; set; }
    }
}

and here is my FormController in API :

private static List<FormData> formsDataList = new List<FormData>();

[HttpPost("submit-form")]
        public IActionResult SubmitForm([FromBody] FormData formData)
        {
            // process the form data
            string carmodel = formData.Carmodel;
            string carnum = formData.Carnum;
            string contactNumber = formData.ContactNumber;
            string option = formData.Option;
            List<string> checkbox = formData.Checkbox;

            string state = formData.State;
            string city = formData.City;



            // validate the form data
 //           if (string.IsNullOrWhiteSpace(carmodel) || string.IsNullOrWhiteSpace(carnum) || string.IsNullOrWhiteSpace(contactNumber) || string.IsNullOrWhiteSpace(option) || checkbox == null || checkbox.Count == 0 || string.IsNullOrWhiteSpace(state) || string.IsNullOrWhiteSpace(city))
  //          {
  //              return BadRequest(new { Message = " Enter the required fields." });
   //         }
            formsDataList.Add(formData);


            //            return Ok(new { Message = "Form submitted successfully." });
            return Ok(formData);

        }

The inputs are not even hitting API. So I suspect the problem is with HTTPClient and with the checkbox.I guess The problem lies with the checkbox. Because if I remove the checkbox field entirely from both HTML form and API, it works perfectly and I’m able to post values to API.

Can someone tell me How to resolve this.

2

Answers


  1. If you log the form value you get this:

    carmodel: "kia"
    ​carnum: "123"
    ​checkbox: true
    ​city: "Chennai"
    ​contactNumber: "456"
    ​option: "Waterwash"
    state: "Tamilnadu"
    

    I think you see the problem too. Boolean isn’t a list of strings. Beside of that you gave for all the three options the same control name.

    You can f. e. use a string array or even better a FormArray and generate the checkboxes with ngFor.

    First I defined the checkbox values:

    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' },
      ];
    

    Btw it is a bit uncommon for me to have values as string. I mean, you will rather store id’s in the database. But anyway.

    Then use a FormArray in the form builder

    checkbox: new FormArray([], Validators.required)
    

    and create a getter for it

    get checkboxesFormArray() {
        return this.form.controls['checkbox'] as FormArray;
      }
    

    After that populate it

    addCheckboxes() {
        this.checkboxes.forEach(() =>
          this.checkboxesFormArray.push(new FormControl(''))
        );
      }
    

    And add an event handler to handle the checked change event

    checkedChanged(e) {
        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('');
        }
      }
    

    This is needed to set the appr. control value to the selected string.

    And this is how the template looks like

      <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>
    

    And here you can find a working stackblitz demo.

    If this is what you are looking for, then please mark it as an answer.

    Login or Signup to reply.
  2. Instead of <input type=checkbox>, you can try using <mat-selection-list>.
    will always return value in boolean. it will return an array of the selected value.
    Code will be:

    <mat-selection-list formControlName="checkbox">
        <mat-list-option value="10%off First service visit"> 10%off First service 
         visit</mat-list-option>
        <mat-list-option value="10%off Waterwash" 10%off Waterwash</label></mat- 
        list-option>
        <mat-list-option value="Free AC Inspection"> Free AC Inspection</mat- 
        list-option>
      </mat-selection-list>
    

    Note: MatSelectionList is a component of Angular Material. You have to import it first in your module.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search