Angular 2/5 displaying a loading spinner during an XMLHttpRequest request

Various loading indicators are used during an xhr request, such as full-page overlays or messages displayed in specific spots on the screen.

I aim to develop a streamlined solution that can be easily implemented across multiple projects with minimal additional work. To achieve this, I have chosen to embed the loading indicator directly within the button being clicked on.

For instance, when clicking on a button labeled "SAVE", I want the button to display a spinner icon next to the word "SAVE" while taking the following actions:

1) Immediately disable the button to prevent further clicks.

2) Show a spinning gif loader beside the word "SAVE", continuing until the XHR response is received.

3) Enable the button again once the XHR response is received.

By placing the spinner within the button, there is no additional footprint or need for extra <div> elements in the HTML.

Could someone provide guidance on the necessary topics to learn for implementing this?

I am familiar with XHR and Angular's (click) event handling. However, I require assistance in managing the appearance and disappearance of the spinner, as well as enabling/disabling the button.

I believe the solution involves techniques like ngStyle, ngClass, mat-icons, and the [disabled] directive for the button, but I need help putting it all together.

Answer â„–1

Even though you're familiar with the challenging parts, let's break it down step by step.

Looking at it from an Angular perspective, there are a few key components:

  • Your button incorporating a (click) handler and [disabled] attribute,
  • A placeholder like <div class="spinner"/>,
  • A service responsible for communicating with the backend.

The general algorithm consists of:

  • Disabling the button and displaying the spinner when "loading" begins,
  • Enabling the button again and hiding the spinner once the "loading" is complete.

Assuming your service is simple:

class MyService {
  constructor(private http: HttpClient) {}

  loadResults() {
    return this.http.get('/api/endpoint');
  }
}

This service will provide an observable that either succeeds, fails, or hangs.

Let's address our objectives. First, handle the button (click) event:

<button (click)="getResults()">Get results</button>

Your component needs to fetch the results and manage them, but only if there isn't already loading in progress. It should also update a "loading" property accordingly.

getResults() {
  if (!this.loading) {
    return;
  }
  this.loading = true;
  this.myService.loadResults()
    .subscribe(results => this.results = results)
    .finally(() => this.loading = false); 
}

We now have a boolean loading flag on the component. Let's utilize it on the component, button, and spinner.

<button (click)="getResults()" [disabled]="loading">Get results</button>

<div class="spinner" [ngClass]="{ hidden: loading }"></div>

With these adjustments, you should be all set.

Edit: In response to your feedback about placing the spinner within the <button> tag itself and using the HTML hidden attribute instead of a CSS class, here's how you can implement it:

<button class="login-button" (click)="checkData()">
  <i [hidden]="!isLoading" class='material-icons'>spinner</i>
  <span [hidden]="isLoading">Log In <i class='material-icons'>arrow_forward</i></span>
</button>

Alternatively, you could completely remove the element from the DOM:

<button class="login-button" (click)="checkData()">
  <i *ngIf="loading" class='material-icons'>spinner</i>
  <span *ngIf="!loading">Log In <i class='material-icons'>arrow_forward</i></span>
</button>

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

What are some ways to display unprocessed image data on a website using JavaScript?

I have an API endpoint that provides image files in raw data format. How can I display this image data on a website using the img tag or CSS background-image property, without utilizing canvas? One possible approach is shown below: $.get({ url: '/ ...

Encountering an issue while trying to convert a JSON object into an array of a specific class type

When I receive a JSON object from a service, I want to iterate through this object and populate an array of class types. Below is the code used to call the service: public GetMapData(): Observable<Response> { var path = 'http://my.blog.net ...

Traveling and mapping in Angular version 5

I'm currently working on a small project using Angular 5 and have set up the router configuration in the code. However, I encountered an issue where clicking a button should navigate to the next view, but although the URL changes, the view remains the ...

I can't seem to get my Angular workspace with multiple projects to build my library. What could be the issue?

In my Angular workspace, I have several projects, one of which is a library that contains shared features. Whenever I attempt to compile my library using ng build my-lib, I am bombarded with a plethora of errors from different projects within the workspac ...

Ways to time animations differently and activate two animations at the same time in every loop

I have 3 hidden text boxes that I want to fade in and slide down simultaneously by 40px when the DOM loads. They should be staggered so that each one triggers after the previous animation finishes. Below is the relevant JavaScript code snippet: jQuery(fu ...

Obtaining legitimate CSS property names for React dynamically

I am looking to create a dropdown menu in React that allows users to select camelized CSS properties (such as width, color, textAlign) for inline styles. Instead of manually inputting all the options for the dropdown, I had the idea of using the React.CSS ...

What is the best way to incorporate a Django variable as the width parameter in a style tag within HTML?

I'm attempting to utilize a Django variable as the percentage width value within a style tag in HTML, but it's not functioning correctly. Strangely, I've discovered that using curly braces {} within style tags is prohibited—this contradict ...

What are the steps to defining a static constant within a TypeScript class?

What is the best way to define a TypeScript static constant within a class so that it can be accessed without initializing the class instance? Below is an example of my class structure: export class CallTree{ public static readonly active = 1; .. ...

What is the best way to include numerous triangles in a single element?

I have designed a timeline featuring milestones with circular images using the CSS property (border-radius: 100%). I am attempting to create arrows at both the top and bottom of each .milestone-image-holder element by utilizing the :before and :after pseud ...

Gradual disappearance of preloader as the page loads

I'm facing an issue with setting a gif as a website preloader. Despite trying different JavaScript solutions, the preloader remains visible even after the page has finished loading. $(window).on("load", function() { $(".loading").fadeOut("slow"); ...

Enhance your map by incorporating an overlay with ngx-openlayers

Currently, I am trying to implement zoom-in and zoom-out buttons on an OpenLayers map. I attempted to use the overlay method but encountered an error. Here is the code snippet for reference: zoom_button = document.getElementById('zoom') zo ...

Issues with CSS animations and transformations on SVG files are not being resolved

I've been attempting to create a transform animation using an SVG file, but unfortunately, the animation or transform isn't functioning at all. I've taken the time to research this issue, however, I haven't found a solution yet. Can any ...

Arranging sibling buttons to wrap seamlessly like text

Is there a way to turn every syllable of a specific phrase into clickable buttons while maintaining regular text wrapping behavior? For reference, in the first image each syllable is plain text, in the second they're wrapped in <span>, and in t ...

Angular's routerLink feature has a tendency to direct me to a completely empty page

I recently started developing my first angular app and I have encountered an issue with navigating on my page using routerLink. The welcome component loads up fine, but when I click on a routerLink, it redirects me to a blank page. import { Component } fro ...

Display Google Maps and YouTube videos once user consents to cookies

I recently installed a plugin on my WordPress site called Cookie Notice, which I found at this link. So far, I've been impressed with how user-friendly and lightweight it is. Due to the latest GDPR regulations, I now need to figure out a way to hide ...

Adjust the height of an element using CSS based on the height of another

Is there a way to have two divs per row, where the second div always displays its full content and the height of the first div matches the height of the second div? If the content in the first div exceeds the height, it should be scrollable. I've atte ...

Guide on applying a CSS shimmer effect to a group of HTML elements simultaneously

I am looking to add a shimmer animation to a group of HTML elements, making it appear as though one continuous shimmer is passing through all the elements. I have observed this effect achieved with text animations using background-clip: text; in CSS and ap ...

Updating the content of a div element to display as a solid color instead of

I am working on creating an interesting hover effect where the background changes dynamically. I want to have a div with an image as the background, overlay (another div) with 50% opacity in any color, and then upon hovering, make the background white. I t ...

Using Jquery to transfer text from a form to a DIV and ensuring the final character is verified

Users can input their name on my HTML form, which will then be displayed in a DIV as part of a book title. The book title includes apostrophes (e.g. Amy's Holiday Album). However, if the user's name ends with an S, I do not want the apostrophe ...

What steps should I take to ensure that this accordion is responsive?

I am currently working on an accordion design and trying to figure out how to make it full width and responsive. I have experimented with various width and display attributes, but I haven't been able to achieve the desired result yet. If you'd l ...