My variable from subscribe is inaccessible to Angular2's NgIf

My goal is to display a spinner on my application while the data is being loaded. To achieve this, I set a variable named IsBusy to True before making the service call, and once the call is complete, I set IsBusy to false.

However, I am facing an issue where the spinner is not being displayed at all in my HTML. Below is the code for both my HTML and TypeScript:

<div id="surgeryRequestFormContainer" class="container-fluid">

        <div *ngIf="isBusy" class="loading">
            <img  src="http://thinkfuture.com/wp-content/uploads/2013/10/loading_spinner.gif"  />
        </div>
     <div class="row">
                <div class="form-group col-sm-12">
                    <button kendoButton (click)="btnPrevious()">Previous</button>
                    <button kendoButton (click)="btnNext()">Next</button>
                    <button kendoButton (click)="btnSaveForLater()">Save For Later</button>

                </div>
            </div>

After researching, I came across a suggestion to import ChangeDetectorRef from '@angular/core'. I followed this advice, instantiated ChangeDetectorRef as cd in my constructor.

 ngOnInit(): void {


        this.isBusy = true;
        console.log("before the subscribe " + this.isBusy);

        this.route.params
            .switchMap((params: Params) => this._RequestFormService.getRequestById(+params['id']))
            .subscribe(
            data => this.Model = data,
            error => console.log("Error", error),
            () => this.isBusy = false);
        this.isBusy = false;
        console.log(this.isBusy);
        this.cd.detectChanges(); // marks path

    }

Despite these efforts, I am still unsure of what steps to take to properly show/hide the spinner div tag.

Answer №1

The reason for the behavior is that the Observable chain is asynchronous. This means that the code does not wait for the chain to complete before moving on to the next line of code. As a result, the call to this.isBusy = false is made almost immediately after setting this.isBusy = true, even before the service call is finished. By the time the service call completes, the spinner has already been closed.

To solve this issue, you should move the call to set this.isBusy = false inside the observable chain.

this.isBusy = true;

this.route.params
    .switchMap((params: Params) => this._RequestFormService.getRequestById(+params['id']))
    .subscribe(
        data => { 
            this.Model = data;
            this.isBusy = false;
        },
        error => console.log("Error", error),
        () => this.isBusy = false);

It's similar to using setTimeout where the code waits for a certain amount of time before executing the next step.

console.log('setting the value to true');

setTimeout(function() {
  console.log('setting the value to false');
}, 1000);

console.log('setting the value to false');

It's important to note that Observables are not strictly asynchronous. Also, the "finally" callback in the subscribe may not be called if the Observable does not complete.

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 could be causing anime.js to malfunction when clicked in Vue.js?

After implementing the mounted() function, the animation now successfully plays when the page is updated. However, there seems to be an issue as the animation does not trigger when clicked. Even though console.log registers a click event, the animation fa ...

Is there a way to display a message in a div container instead of using the alert box when there is a successful ajax response?

Hey there, I'm currently working on implementing error validation handling for a custom form that I've created. I'm looking to display the error messages in a designated div rather than using the standard browser alert box. Since I'm fa ...

Angular 14 Custom Validator Assistance

I need help understanding how to incorporate a custom validator in my reactive form. I have 15 fields, and 3 of them are related to the custom validators "tcpPorts", "udpPorts", and "icmp" (a checkbox). The requirement is that at least one of these three f ...

The perplexing results received when using the npm outdated command

Could someone provide an explanation for the meaning behind this output? $ npm --version 3.10.8 $ npm -g outdated npm Package Current Wanted Latest Location npm 3.10.8 4.0.2 3.10.9 As stated in the documentation, the "Wanted" column should d ...

"An error has occurred stating that the function Factory.function() in AngularJS

I'm a beginner with AngularJS and could use some assistance! My issue involves retrieving JSON data from a URL in a factory function and returning it to the controller. However, I keep getting an error stating that the function doesn't exist. Wh ...

Typescript is struggling to accurately infer extended types in some cases

My goal is to optimize the body of a NextApiRequest for TypeScript. I currently have this code snippet: // This is a type from a library I've imported export interface NextApiRequest { query: Partial<{ [key: string]: string | string[]; ...

AngularJS enables seamless two-way data binding with DropDownList in the Model-View-Controller (M

As a beginner in AngularJS, I am currently experimenting with implementing 2-way data binding for the Gender Dropdown menu similar to what I have done with textboxes. Below is a snippet of code for the dropdown control: <div class="form-group"> ...

Efficient methods to transfer values or arrays between components in Angular 8 without relying on local storage

I am working on a project that involves two components: a login component and a home component. I need to pass user data from the login component to the home component without using local storage. Is there a way to achieve this in Angular 8? Below is the ...

Is it possible to transfer a child from one parent to another using JavaScript?

I need help with moving an element from one parent to another using JavaScript, preferably using the jQuery library. Original code: <div id = "div1"> <p id = "paragraph"> Lorem ipsum dolor sit amet, adipiscing pellentesque egestas. &l ...

How can AngularJS handle multiple routes using unique templates while sharing the same controller?

I am currently researching whether I can achieve the functionality described in the title. Here are my initial thoughts: Let's consider the following routes I have set up: .when('/', { templateUrl : 'partials/homepage.html&ap ...

Coldfusion: The Troubles of an Empty Link href="#" Error

For my CFWheels Coldfusion project, I have been utilizing Adobe Coldfusion Builder 3. In Coldfusion, when you want to output a variable, you typically do something like this: #variable_name# However, I am interested in incorporating an empty link into m ...

Encountered difficulty retrieving properties from the req.query object within expressjs

My setup includes a router configuration like this: router.get('/top-5-cheap', aliasTopTours, getAllTours); I've also implemented some middlewares: Middleware aliasTopTours: In this middleware, I am setting certain properties on the reque ...

Display an icon button when a user edits the text in a text field, and make it disappear once clicked on

Figuring out how to incorporate a v-text-area with an added button (icon) that only appears when the text within the text area is edited, and disappears once it is clicked on, has proven to be quite challenging. Below is a simplified version of my code to ...

Can you provide information on the type signature of the `onChange` event for the MUI DatePicker?

I am utilizing an instance of the MUI DatePicker along with a MomentAdapter: import *, {useState} as React from 'react'; import TextField from '@mui/material/TextField'; import { AdapterMoment } from '@mui/x-date-pickers/AdapterMom ...

Error: Unable to retrieve the value as the property is null

I'm a beginner in jQuery and I'm attempting to create a login form that displays a message when the user enters a short username. However, despite my efforts, the button does not trigger any action when clicked. Upon checking the console, it indi ...

Retrieve the attribute from the element that is in the active state

I'm facing a challenge in determining the active status of an element attribute. I attempted the following approach, but it incorrectly returned false even though the element had the attribute in an active state - (.c-banner.active is present) During ...

Prevent the countdown timer from resetting every time I refresh the page

Whenever I refresh my page, the timer starts over. I want it to pick up from where it left off until it reaches 0. This is my JavaScript code for handling the timer: var target_date = new Date().getTime() + (1000*3600*48); // set the countdown date var ...

What's the best way to show floating point numbers in a concise format while also maintaining the ability to perform calculations within this Vue app?

I'm currently developing a compact calculator application using Vue 3 and implementing some custom CSS. For the most part, everything seems to be functioning correctly, except for when the results are long numbers that extend beyond the display limit ...

PHP can display content directly in the browser, without the need for jQuery

As I develop a web interface for an application that has longer processing times, a loading page is displayed to the user when it starts. An AJAX call then loads the output onto the page. Strangely, while browsing the PHP function directly in the browser r ...

What is the best way to display breadcrumb text on a new line within a pop up when the width exceeds without resorting to a scroll bar

Presently, my breadcrumb has a scrollable wrap with text overflowhttps://i.sstatic.net/dhllv.png I want to make the overflowed text continue on the next line. How can I achieve this? The CSS code I am using for the image attached is as follows: .breadcrumb ...