skip to Main Content

I have made use of a generic approach where on adding a food item, a modal with a form will open to let the user add his details. However, for the check on backend for duplicate items, i can only retrieve that after the api call has finished.

The thing is I dont want the modal to be close if there is error as user has to fill all his details again.

Here is my code. I have used third party libraries for modal and toast.

food.component.ts :

addFood(data: any){
    this.api.request('foodItem', 'POST', data).subscribe({
        next: (response: any) => {
            if (response.message == 'Added Successfully.') {
                this._toastService.showSuccess('Food added.');
            } else {
                this._toastService.showError(response.message);
            }
        },
        complete: () => this.getFood(),
        error: (error: any) => this._toastService.showError(error.message)
    });
}

custom – table.component.html

<button type = "button" class="btn btn-link"(click) = "openModal()"[disabled] = "isRowSelected"><span>Add</span></button>
<button type="button" class="btn btn-link"(click) = "openModal(selectedRow)"[disabled] = "isRowNotSelected"></i><span>Edit</span></button>

custom – table.component.ts :

openModal(rowData: any = null) {
    const config: Partial<DynamicFormComponent> = {
        form: this.form,
        data: rowData
    };

    const options: NgbModalOptions = { size: 'sm', centered: true };

    this.ModalService.show((DynamicFormComponent), config, options).subscribe((result: any) => {
        if (result.Success == true && result.Data) {
            if (rowData) {
                const updatedRowData = { ...rowData, ...result.Data };
                // If rowData is provided, it's an edit operation
                this.onEdit.emit(updatedRowData);
            } else { //add
                this.onAdd.emit(result.Data);
            }
        }
    });
}

How to solve this?

2

Answers


  1. You can cancel the hide.bs.modal event, based on your condition

    $("#exampleModal").on("hide.bs.modal", function(event) {
      if (!document.querySelector("#defaultCheck1").checked) {
        event.preventDefault();
      }
    });
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    
    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
      Launch demo modal
    </button>
    
    <!-- Modal -->
    <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <div class="form-check">
              <input class="form-check-input" type="checkbox" value="" id="defaultCheck1">
              <label class="form-check-label" for="defaultCheck1">
        Allow Closing
      </label>
            </div>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
    
          </div>
        </div>
      </div>
    </div>
    Login or Signup to reply.
  2. Not use "close". Add to your component in modal a Subject, and subscribe when open. Is the component that open the popup who close the popup

    //in your component in a popup
        @Input() form: FormGroup;
        submit:Subject<any>=new Subject<any>()
    
    //in .html
    <div class="modal-header">
      <h4 class="modal-title">Hi there!</h4>
      <button type="button" class="btn-close" aria-label="Close"
               (click)="activeModal.dismiss()"
      ></button>
    </div>
    <div class="modal-body">
      <p>Hello, {{ name }}!</p>
      <!--A typical form-->
      <div [formGroup]="form">
        <input formControlName="name" />
      </div>
    </div>
    <div class="modal-footer">
      <button
        type="button"
        class="btn btn-outline-dark"
        <!--see that only emit one value to the "submit" subject -->
        (click)="submit.next(form.value)"
      >
        Close
      </button>
    </div>
    

    Then, when open

      open() {
        const modalRef = this.modalService.open(NgbdModalContent);
        modalRef.componentInstance.name = 'World';
        modalRef.componentInstance.form = this.form;
        modalRef.componentInstance.submit
          .pipe(takeUntil(modalRef.closed))
          .subscribe((data: any) => {
            //I use a simple service that return "true" or "false"
            this.dataService.checkData(data.name).subscribe((res: any) => {
              if (res) modalRef.close(); //<--this close the popUp
            });
          });
      }
    

    A stackblitz (only close if you write "Angular" in the "name")

    NOTE: you can improve indicating the reason it’s not valid the "form" or you can use a custom async validator.

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