What could be causing the spinner to remain open even after the API has finished executing on my UI?

I am facing an issue with displaying a spinner while waiting for my API to complete. When I click the onSave button, the spinner appears as expected. However, even after the API call is completed, the spinner remains visible. How can I make sure the spinner closes after the API call is finished?

public onSave() {
  this.isSaving = true
    this.formService.entityForm.markAsPristine();
    this.visaSubmitHandler.execute({ application: this.formService.entityForm.value }).subscribe({
        next: (response: IApplicationCreateResponse) => {
            this.stateRehydrationService.clearStateKey(this.formService.key);
            this.visaSuccessHandler.execute({ application: response.entity });
        },
        error: (response: IApplicationCreateResponse) => {
            this.formService.entityForm.markAsDirty();
            try {
                for (const error of response.errors) {
                    const propertyName = `${error.propertyName[0].toLowerCase()}${error.propertyName.slice(1)}`
                    const control = this.formService.entityForm.get(propertyName) as AbstractControl;
                    setErrors({ serverError: error.message }, control);
                }

                this.bottomSheet.open(DisplayErrorsComponent, { data: response.errors.map(e => e.message) });
            } catch (e) {
                console.error(e);
            }
        },
        complete: () => {
          this.isSaving = false
        }
    })
}
<div class="overlay" *ngIf="isSaving">
    <div class="spinner-container">
      <mat-spinner></mat-spinner>
    </div>
  </div>

Answer №1

The straightforward explanation is that within your template, the variable isProcessing still holds the value true.

Therefore,

  • Either the change detection has been disabled using OnPush (in this situation, you need to manually use changeDetectorRef.markForCheck() immediately after setting this.isProcessing = false;)
  • Or the observable
    this.formSubmissionHandler.execute
    is not completing (in this case, you can set this.isProcessing = false; in your next: block or make sure the observable is properly closed.

Answer №2

Here is an enhanced version of your script:

import { ChangeDetectorRef } from '@angular/core';

// ...

constructor(private cdr: ChangeDetectorRef) {}

public onSave() {
  this.isSaving = true;

  this.formService.entityForm.markAsPristine();
  
  this.visaSubmitHandler.execute({ application: this.formService.entityForm.value }).subscribe({
    next: (response: IApplicationCreateResponse) => {
      this.stateRehydrationService.clearStateKey(this.formService.key);
      this.visaSuccessHandler.execute({ application: response.entity });
    },
    error: (response: IApplicationCreateResponse) => {
      this.formService.entityForm.markAsDirty();
      try {
        for (const error of response.errors) {
          const propertyName = `${error.propertyName[0].toLowerCase()}${error.propertyName.slice(1)}`
          const control = this.formService.entityForm.get(propertyName) as AbstractControl;
          setErrors({ serverError: error.message }, control);
        }

        this.bottomSheet.open(DisplayErrorsComponent, { data: response.errors.map(e => e.message) });
      } catch (e) {
        console.error(e);
      }
    },
    complete: () => {
      this.isSaving = false;
      this.cdr.detectChanges(); // Activate change detection
    }
  });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can the order of event bubbling be altered in JavaScript?

I have three boxes in my HTML, each with its own click events. Currently, when I click on a child element, event bubbling occurs in the order of C->B->A. However, I am curious to see if it's possible to change the event bubbling order to C-> ...

Utilizing RXJS in Angular to pull information from numerous services within a single component

There are two services, ser1 and ser2. getdata1() { this.http.get<{message:string,Data1:any}>('http://localhost:3000/api/1') .pipe(map((data1)=>{ return Data1.Data1.map(data=>{ return { id: d ...

Nested Classes in JQuery

Looking for help with fading in text using jQuery. Despite setting everything up, it doesn't seem to be working. Can someone assist me with this issue? Here is my current code: .nav ul li { opacity: 0; padding: 0px 50px; transition: opacity 2s ease-i ...

Steps for arranging text in a dropdown list option

How can I format 3 words in a dropdownlist option so they are aligned properly? eg. <option value="1">ABCDE - ALPHA</option <option value="2">1234 - NUMERIC</option> <option value="3">ABC123 - ALPHANUMERIC</option> I woul ...

Steps for implementing a custom loader in a JHipster project instead of the default pacman loader

Seeking assistance to customize the loader for the jhipster initial page. Currently, it is loading the default packman loader of the jhipster application. Any help would be greatly appreciated. Thank you in advance. ...

An H1 tag that has a class will take on the attributes of the h1 heading

During my CSS practice, I encountered some confusion regarding Class Selectors. Specifically, I had styled a H1 tag and then applied additional styles to a H1 tag with a class. To my surprise, the H1 tag with a class was inheriting properties from the orig ...

Using CSS to conceal an element when a different element is also invisible

My inquiry is as follows: I currently possess a code that conceals class element 1 when it possesses a specific value (which varies across different sites). Now, my objective is to also conceal class element 2 ONLY IF class element 1 is already hidden. ...

In PHP forms, ensure that only completed textboxes are submitted and empty textboxes are discarded

I've created a form that displays all available products from a database along with their prices. Users can input the quantity they want to purchase for each product, and upon submission, the total amount will be calculated. There are 5 products in th ...

Guidance on incorporating static files with Spring MVC and Thymeleaf

I'm seeking guidance on how to properly incorporate static files such as CSS and images in my Spring MVC application using Thymeleaf. Despite researching extensively on this topic, I have not found a solution that works for me. Based on the recommenda ...

Saving the retrieved data from a JQuery $.post request into a JavaScript global variable

Currently utilizing Javascript and JQuery. A declaration of a Variable var RoleID=""; is stationed outside all functions. There exists a function: role_submit(){ var role=$('#emp_role').val(); var url="submitrole.php"; $.post(url, {role2: rol ...

What is the best way to loop through an array that contains a custom data type

When I declared the type: export interface Type{ id: number; name: string; } I attempted to iterate over an array of this type: for(var t of types) // types = Type[] { console.log(t.id); } However, I encountered the following error message: ...

Using VBA to Populate Dropdown List on Webpage from an iFrame

I am facing an issue with my code that aims to interact with a webpage by clicking on a link and then modifying dropdown lists within an Iframe. Specifically, I am attempting to populate the Manufr dropdown list based on data from the Year iFrame using VBA ...

Issues encountered with AngularJs filter search functionality

Why am I having trouble adapting this search filter from here? This is what my code looks like: controllers.js angular.module('starter.controllers', ['starter.services']) .controller('AppCtrl', function($scope, $ionicModal ...

Using JavaFX to showcase FontAwesome icons

I've been working on a project to create a custom icon class that can load FontAwesome icons, but I'm facing issues with reading the fontawesome-webfont.ttf file. Here is the code for creating an icon: import javafx.scene.control.Label; import ...

Apache Wicket - Utilizing HTML5 details element within a RepeatingView to save open property

In my repeatingview, I have HTML5 detail elements that can be opened or collapsed by the user. However, when I remove certain elements from the repeatingview and then reload it using target.add(container), all elements end up being collapsed again. How c ...

Ways to achieve the organization of nested promises in Angular 9

I am facing an issue with the order of asynchronous calls in my Angular script. Despite having multiple nested async calls, the order of execution seems to be disrupted. Here is a snippet of my Angular code: saveArticles(articles, action) { articles.f ...

Foundation 6: Alignment issues with Top Bar

Exploring Foundation 6 and trying out the sample code. I'm puzzled as to why the "Site Title" is not in alignment with the rest of the top-bar, it seems to be slightly higher up. <div class="top-bar"> <div class="top-bar-title"> ...

What could be causing the misalignment of the Datepicker calendar in Material UI?

I have integrated a datepicker using the library "@mui/x-date-pickers/DatePicker". import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; import { Locali ...

Create circles with a variety of different colors on the canvas

I need assistance with creating an animation where circles move from right to left on a canvas. The colors of the circles are randomly selected using a function. Currently, I have a fiddle where a single circle moves from right to left, changing color ever ...

Having trouble implementing two-way binding in Angular for a specialized component?

Within my view component, I am fetching data from a service and setting it as a property. Custom components then use these fields to display the data. Everything seems to be working fine so far. <app-textbox [caption]="'First name'" ...