Search code examples
angularangular-materialangular6

To close dialog component based on api response


I have component called AddCustomerComponent which i am calling as dialog component,In the AddCustomerComponent after filling the input fields i am performing POST operation.Now POST operation working fine.

But after POST operation based on the api response, I want perform following operations:

  • If POST is successful,then dialog(AddCustomerComponent) should close.
  • If not,then dialog should not close.

Below are my component code and service file codes:

HTML

<form [formGroup]="addForm">
    <mat-form-field>
        <input matInput placeholder="Name" formControlName="name" required>
        <mat-error *ngIf="addCusForm.controls.name.hasError('required')">
            Please enter your name
        </mat-error>
    </mat-form-field>
    <mat-form-field>
        <input placeholder="Email Address"  formControlName="email" required>
        <mat-error *ngIf="addCusForm.controls.email.hasError('required') ">
            Please enter email address
        </mat-error>
    </mat-form-field>
    <button mat-flat-button  type="submit" (click)="onAddCustomer()">Save</button>
    <button mat-flat-button  type="button">Cancel</button>  
</form>

TS

import { Component, OnInit } from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  Validators,
} from '@angular/forms';
import { MatDialog, MatDialogRef } from '@angular/material';
import { ICustomer } from 'src/app/models/app.models';
import { CustomersService } from 'src/app/services/customers.service';

@Component({
  selector: 'awa-add-customer',
  templateUrl: './add-customer.component.html',
  styleUrls: ['./add-customer.component.css'],
})
export class AddCustomerComponent implements OnInit {
  public addForm: FormGroup;
  public someCustomer: ICustomer;

  constructor(
    private fb: FormBuilder,
    public dialog: MatDialog,
    public customersService: CustomersService,
  ) {}

  public ngOnInit(): void {
    this.addForm = this.fb.group({
      name: [null,[Validators.required]],
      email: [null,[Validators.required]],
    });
  }

  public onAddCustomer(): void {
    this.someCustomer = this.addForm.value;
    this.customersService.addCustomer(this.someCustomer);
  }

}

Service Fle

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ICustomer } from 'src/app/models/app.models';

@Injectable({
  providedIn: 'root',
})

export class CustomersService {
 private  baseUrl : string = '....api URL.....';

 constructor(private http: HttpClient) {}

  public async addCustomer(customer: ICustomer ): Promise<void>  {
    const apiUrl: string = `${this.baseUrl}/customers`;
    let temp : any;
    temp =  this.http.post(apiUrl, customer).subscribe(data => {
        alert('Customer added successfully');
    },error => {
        console.log(error);
    });
  }

}

Solution

  • You simply have to return the promise of the Post call from your service, and subscribe to it to close the dialog wheter or not the http call has gone well.

    First, don't forget to return your promise in the service method:

    public addCustomer(customer: ICustomer ): Promise<void>  {
      const apiUrl: string = `${this.baseUrl}/customers`;
      return this.http.post(apiUrl, customer);
      // I removed the subscribe() here since you can have only one per promise
      // But you can use Rxjs 'pipe' operation if necessary.
    }
    

    Then, subscribe to the promise when calling the addCustomer() method:

    public onAddCustomer(): void {
      this.someCustomer = this.addForm.value;
      this.customersService.addCustomer(this.someCustomer).subscribe(
        () => // POST is ok, close dialog,
        (error) => // do nothing, or alert
      );
    }
    

    EDIT: The previous snippet has been deprecated and will be removed in RxJS v8. Docs: https://rxjs.dev/deprecations/subscribe-arguments The new suggested method is to use an object parameter to specify which callback to use.

    public onAddCustomer(): void {
       this.someCustomer = this.addForm.value;
       this.customersService.addCustomer(this.someCustomer).subscribe({
          next: (v) => console.log(v),
          error: (e) => console.error(e),
          complete: () => console.info('complete') 
       });
    }
    

    If you only use the next callback, it is recommended to simply pass in an anonymous function:

    public onAddCustomer(): void {
       this.someCustomer = this.addForm.value;
       this.customersService.addCustomer(this.someCustomer).subscribe((v) => console.log(v));
    }