Search code examples
angularrestpostput

Angular sends the same request twice when putting data


I am trying to create a web UI in Angular for a restful service I have made. When I try to make a put or post request from angular it sends the request twice and adding the same data to the RESTfull service twice. I have included a screenshot of the two XHR requests and the code I am using to put data onto the server. Does anyone have any thoughts as to why this is happening? Thanks

Angular Code:

addOccupation(occupation: Occupation): Observable<any>{
    return this.http.put<{Response, Occupation}>(this.url + 'occupation/insert', occupation, { headers: { 'Content-Type': 'application/json'}})
  }

  addAddress(address: Address): Observable<any>{
    return this.http.put<{Response, Address}>(this.url + 'address/insert/', address, { headers: { 'Content-Type': 'application/json'}})
  }

  addPerson(person: Person): Observable<any>{
    return this.http.put<{Response, Person}>(this.url + 'person/insert/', person, { headers: {'Content-Type': 'application/json',}})
  }

New Commonent HTML Code


<form [formGroup]="addUser" (ngSubmit)="onSubmit()">
  <h5 *ngIf="added">Your person was successfully added to the database!</h5>
  <h5 *ngIf="added==false && submitted">Your person was not added to the database!</h5>
  <mat-form-field>
    First Name:
    <input matInput type="text" formControlName="firstName">
    <div *ngIf="submitted && addUser.controls.firstName.errors" class="error">
      <div *ngIf="addUser.controls.firstName.errors.required">First Name is Required!</div>
    </div>
  </mat-form-field>
  <br>
  <mat-form-field>
    Middle Name:
    <input matInput type="text" formControlName="middleName">
    <div *ngIf="submitted && addUser.controls.middleName.errors" class="error">
      <div *ngIf="addUser.controls.middleName.errors.required">Middle Name is Required!</div>
    </div>
    </mat-form-field>
    <br>
  <mat-form-field>
     Last Name:
    <input matInput type="text" formControlName="lastName">
    <div *ngIf="submitted && addUser.controls.lastName.errors" class="error">
      <div *ngIf="addUser.controls.lastName.errors.required">Last Name is Required!</div>
    </div>
  </mat-form-field>
  <br>
  <mat-form-field>
    Home Phone:
   <input matInput type="text" formControlName="homePhone">
   <div *ngIf="submitted && addUser.controls.homePhone.errors" class="error">
     <div *ngIf="addUser.controls.homePhone.errors.required">Home Phone is Required!</div>
   </div>
 </mat-form-field>
 <br>
 <mat-form-field>
  Mobile Phone:
 <input matInput type="text" formControlName="mobilePhone">
 <div *ngIf="submitted && addUser.controls.mobilePhone.errors" class="error">
   <div *ngIf="addUser.controls.mobilePhone.errors.required">mobilePhone is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Work Phone:
 <input matInput type="text" formControlName="workPhone">
 <div *ngIf="submitted && addUser.controls.workPhone.errors" class="error">
   <div *ngIf="addUser.controls.workPhone.errors.required">Work Phone is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Home Email:
 <input matInput type="text" formControlName="homeEmail">
 <div *ngIf="submitted && addUser.controls.homeEmail.errors" class="error">
   <div *ngIf="addUser.controls.homeEmail.errors.required">Home Email is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Work Email:
 <input matInput type="text" formControlName="workEmail">
 <div *ngIf="submitted && addUser.controls.workEmail.errors" class="error">
   <div *ngIf="addUser.controls.workEmail.errors.required">Work Email is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Height (cm):
 <input matInput type="number" formControlName="height">
 <div *ngIf="submitted && addUser.controls.height.errors" class="error">
   <div *ngIf="addUser.controls.height.errors.required">Height is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Weight (lbs):
 <input matInput type="number" formControlName="weight">
 <div *ngIf="submitted && addUser.controls.weight.errors" class="error">
   <div *ngIf="addUser.controls.weight.errors.required">Weight is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Gender:
 <input matInput type="text" formControlName="gender">
 <div *ngIf="submitted && addUser.controls.gender.errors" class="error">
   <div *ngIf="addUser.controls.gender.errors.required">Gender is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Race:
 <input matInput type="text" formControlName="race">
 <div *ngIf="submitted && addUser.controls.lastName.errors" class="error">
   <div *ngIf="addUser.controls.race.errors.required">Race is Required!</div>
 </div>
</mat-form-field>
<br>
  <mat-form-field>
      House Number:
     <input matInput type="number" formControlName="number">
     <div *ngIf="submitted && addUser.controls.number.errors" class="error">
       <div *ngIf="addUser.controls.number.errors.required">House number is Required!</div>
     </div>
   </mat-form-field>
   <br>
   <mat-form-field>
      Street Name:
     <input matInput type="text" formControlName="street">
     <div *ngIf="submitted && addUser.controls.street.errors" class="error">
       <div *ngIf="addUser.controls.street.errors.required">Street Name is Required!</div>
     </div>
   </mat-form-field>
   <br>
   <mat-form-field>
      City:
     <input matInput type="text" formControlName="city">
     <div *ngIf="submitted && addUser.controls.city.errors" class="error">
       <div *ngIf="addUser.controls.city.errors.required">City is Required!</div>
     </div>
   </mat-form-field>
   <br>
   <mat-form-field>
      State:
     <input matInput type="text" formControlName="state">
     <div *ngIf="submitted && addUser.controls.state.errors" class="error">
       <div *ngIf="addUser.controls.state.errors.required">State is Required!</div>
     </div>
   </mat-form-field>
   <br>
   <mat-form-field>
      Zip Code:
     <input matInput type="text" formControlName="zip">
     <div *ngIf="submitted && addUser.controls.state.errors" class="error">
       <div *ngIf="addUser.controls.zip.errors.required">Zip Code is Required!</div>
     </div>
   </mat-form-field>
   <br>
   <mat-form-field>
      Company Name:
     <input matInput type="text" formControlName="companyName">
     <div *ngIf="submitted && addUser.controls.companyName.errors" class="error">
       <div *ngIf="addUser.controls.companyName.errors.required">Company Name is Required!</div>
     </div>
   </mat-form-field>
   <br>
   <mat-form-field>
    Job Title:
   <input matInput type="text" formControlName="jobTitle">
   <div *ngIf="submitted && addUser.controls.jobTitle.errors" class="error">
     <div *ngIf="addUser.controls.jobTitle.errors.required">Job Title is Required!</div>
   </div>
 </mat-form-field>
 <br>
 <mat-form-field>
  Employment Type:
 <input matInput type="text" formControlName="employmentType">
 <div *ngIf="submitted && addUser.controls.employmentType.errors" class="error">
   <div *ngIf="addUser.controls.employmentType.errors.required">Employment Type is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Monthly Salary:
 <input matInput type="text" formControlName="monthlySalary">
 <div *ngIf="submitted && addUser.controls.monthlySalary.errors" class="error">
   <div *ngIf="addUser.controls.monthlySalary.errors.required">Monthly Salary is Required!</div>
 </div>
</mat-form-field>
<br>
<mat-form-field>
  Industry:
 <input matInput type="text" formControlName="industry">
 <div *ngIf="submitted && addUser.controls.industry.errors" class="error">
   <div *ngIf="addUser.controls.industry.errors.required">Industry is Required!</div>
 </div>
</mat-form-field>
    <br>
  <button mat-raised-button color="primary" (click)="onSubmit()">Add User</button>
</form>

On Submit function

onSubmit(){
  this.submitted = true;

  if(this.addUser.invalid){
    return;
  }

  this.success=true;
  if(this.success){
    var person = new Person()
    var address = new Address()
    var occupation = new Occupation()
    person.firstName = this.addUser.value.firstName
    person.middleName = this.addUser.value.middleName
    person.lastName = this.addUser.value.lastName
    person.homePhone = this.addUser.value.homePhone
    person.mobilePhone = this.addUser.value.mobilePhone
    person.workPhone = this.addUser.value.workPhone
    person.homeEmail = this.addUser.value.homeEmail
    person.workEmail = this.addUser.value.workEmail
    person.height = this.addUser.value.height
    person.weight = this.addUser.value.weight
    person.gender = this.addUser.value.gender
    person.race = this.addUser.value.race
    address.number = this.addUser.value.number
    address.street = this.addUser.value.street
    address.city = this.addUser.value.city
    address.state = this.addUser.value.state
    address.zip = this.addUser.value.zip
    occupation.companyName = this.addUser.value.companyName
    occupation.jobTitle = this.addUser.value.jobTitle
    occupation.employmentType = this.addUser.value.employmentType
    occupation.monthlySalary = this.addUser.value.monthlySalary
    occupation.industry = this.addUser.value.industry
    this.data.addOccupation(occupation)
    .subscribe
    (
      data =>
      {
          person.occupationId = data.id;
          this.data.addAddress(address)
          .subscribe
          (
            data =>
            {
                person.addressId = data.id
                this.data.addPerson(person)
                .subscribe
                (
                  resp =>
                  { 
                    if(resp.id!=null){
                      this.added = true;
                    }else{
                      this.added = false;
                    }              
                  },
                  data => 
                  {
                    this.objPerson = data

                  }
                )
      }
    )
      }
    )

  }
}

Angular Put Request #1

Angular Put Request #2

Console Error and logs


Solution

  • You have (ngSubmit)="onSubmit()" and <button mat-raised-button color="primary" (click)="onSubmit()">Add User</button> in the HTML.

    Remove one.

    I would also write the RxJS stream like so:

    import { switchMap } from 'rxjs/operators';
    ....
    this.data.addOccupation(occupation).pipe(
      switchMap(occupation => {
        person.occupationId = occupation.id;
        return this.data.addAddress(address);
      }),
      switchMap(address => {
        person.addressId = address.id;
        return this.data.addPerson(person);
      })
    ).subscribe(
      resp => {
        if (resp.id !== null) {
          this.added = true;
        } else {
          this.added = false;
        }
      } // I am not sure how you are assigned `this.objPerson = data` 
        // but you can do it in this subscribe
    )
    

    This way you avoid callback hell with the subscribes.