0

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.

7
  • Is there any more info in the response of the 400 request? Commented Mar 31, 2023 at 14:09
  • make sure you are using the right port and url localhost:7095/api/Forms/submit-form Commented Mar 31, 2023 at 14:11
  • @Alexander Ive updated the code with errors Commented Mar 31, 2023 at 14:15
  • @DEV it is right, jus double checked . Is there a problem with the way I try to post Commented Mar 31, 2023 at 14:17
  • 1
    So the payload that you send to the api is not correct(required fields? missing fields? too many fields?). Compare the payload with your model. One difference I notice is Selectcity <> city Commented Mar 31, 2023 at 14:23

1 Answer 1

1

With the [FromForm] attribute, your API expects to receive the form data with the Content-Type: application/x-www-form-urlencoded. But on the Angular side, you are posting the request body with the Content-Type: application/json.

Thus, the API cannot process the request and return the response with a 400 status code.


Solution 1: Post request data as JSON body.

Use [FromBody] attribute instead of [FromForm] attribute.

[HttpPost("submit-form")]
public IActionResult SubmitForm([FromBody] FormData formData)

Solution 2: Send the request data with the Content-Type: application/x-www-form-urlencoded.

export class CarServiceService {

  addCar(formData : any): Observable<any> {
    let body = new URLSearchParams();
    body.set('carmodel', formData.carmodel);
    body.set('carnum', formData.carnum);
    body.set('contactNumber', formData.contactNumber);
    body.set('option', formData.option);

    for (let c of formData.checkbox)
      body.set('selectedCheckboxes[]', c);

    body.set('selectstate', formData.state);
    body.set('selectcity', formData.city);

    return this.http.post<any>('https://localhost:7095/api/Forms/submit-form', body);
  }
}

And note that a 400 Bad Request status could happen when the API is unable to deserialize the request body and map to the parameter due to the unmatched field/property type. For example, in Angular, you are sending the checkbox as string in Angular, but formData.SelectedCheckbox is expecting a value with List<string> type.

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

8 Comments

hey just tried solution 2, I get this error 'TypeError: formData.checkbox is not iterable'. I guess I Should make checkbox an array, But i dont really know how to do that
Yes, I implement the sending request body based on your model data type in API. To achieve the checkbox as array, you should use FormArray in your Reactive Form.
Imported, But unsure of using it in forms. Should I use it in html?
I think will be due to unmatched data type for checkbox type in Angular which is string, while your API expects the checkbox as List<string> type.
I made the change but I get this error all over the code "Property 'checkbox' comes from an index signature, so it must be accessed with ['checkbox']."
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.