Anuj TBE
Anuj TBE

Reputation: 9800

display a pre-loader in Angular before it load first component

I'm using Angular 6.

My application takes a few seconds before it loads the component and that time is spent in loading resources and validating the user.

While all this happens, my application displays a blank white page.

I want to replace that ugly white page with a preloader that will be displayed until all background process is complete.

For that I have added a CSS loading spinner inside the index.html like

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My App</title>
  <base href="/">

  <!-- Fonts and icons -->

</head>
<body>
  <app-root>
    <!-- Pre-loading spinner -->
    <!-- This code within the app-root will be wiped of once the child component is loaded -->
    <!-- This code will not even be shown in the source code once the child component is loaded -->
    <!-- We can put any code css/html/image/etc here -->

    <style>
      /** CSS here. Since it will be wiped totally, 'll not cause any impact to the core stylesheet.
    </style>

    Loading<span class="d">.</span><span class="d d-2">.</span><span class="d d-3">.</span>
  </app-root>
</body>
</html>

And this displays a page like

enter image description here

But the issue is that. The first loaded component is app.component.html which has following content

<router-outlet></router-outlet>

Which further loads another component admin-layout-component.html with contents

<div class="wrapper">
  <div class="sidebar" data-color="red">
    <app-sidebar></app-sidebar>
  </div>
  <div class="main-panel">
    <app-navbar></app-navbar>
    <router-outlet></router-outlet>
    <app-footer></app-footer>
  </div>
</div>

As soon as app.component is loaded, the spinner content from index.html is removed and start displaying the blank page until admin-layout is loaded.

I tried adding same styling code inside the router-outlet of app.component.html but then when the component is loaded, the contents are added along with the spinner and spinner is not removed from other pages.

How can I display the spinner on app.component.html as well until dashboard page is loaded.

Here is a video how it is working: https://youtu.be/RSlTi0EQHm4

Upvotes: 17

Views: 30650

Answers (3)

OMANSAK
OMANSAK

Reputation: 1332

Component

@Component({
  selector: 'body[osk-root]',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent{/* Not need remove element or change style*/}

index.html

<body osk-root><!--YOUR LOADER--></body>

after appcomponent succefully loaded , angular clears innerHtml of body[osk-root] element

Upvotes: 9

Jimmy Garpeh&#228;ll
Jimmy Garpeh&#228;ll

Reputation: 473

I got this working in Angular 8, based on Sunil's answer. I'm hiding the loader element from the App Component, which is initialized before any other component. So no need to add this everywhere.

Manipulating the DOM using ElementRef is not recommended so I'm using Renderer2 instead.

index.html:

<body class="theme-primary">
  <div id="loader">
    <style>
      .application-loading-container {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        height: 100vh;
      }

      .application-loading-box {
        width: 300px;
        margin: 5px;
        text-align: center;
      }
    </style>
    <div class="application-loading-container">
      <div class="application-loading-box"><h2>Loading...</h2></div>
    </div>
  </div>
  <app-root></app-root>
</body>

app.component.ts:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements AfterViewInit {
  constructor(private renderer: Renderer2) {}

  ngAfterViewInit() {
    let loader = this.renderer.selectRootElement('#loader');
    this.renderer.setStyle(loader, 'display', 'none');
  }
}

Upvotes: 17

Sunil
Sunil

Reputation: 11243

First of all your implementation is pretty standard way to show the loading spinner.

Issue

The issue is not with the app component. Spinner is disappearing after the app component is loaded. The blank page you are seeing because of Dashboard Component which is huge in size and it could have multiple API calls. So basically spinner is working as expected. Issue is with Dashboard Component

Fix

1.If you want to fix then you need hide handle spinner in the Dashboard Component. Create the a and put your spinner content in it instead of <app-root>

<body>
  <div id="loader">
     <!-- Pre-loading spinner -->
    <!-- This code within the app-root will be wiped of once the child component is loaded -->
    <!-- This code will not even be shown in the source code once the child component is loaded -->
    <!-- We can put any code css/html/image/etc here -->

    <style>
      /** CSS here. Since it will be wiped totally, 'll not cause any impact to the core stylesheet.
    </style>

    Loading<span class="d">.</span><span class="d d-2">.</span><span class="d d-3">.</span>
  </div>

  <app-root></app-root>
</body>

Dashboard Component

Hide the div with id loader in ngAfterViewInit

@Component({selector: 'dashbaord', template: `...`})
class DashboardComponent implements AfterViewInit {
  constructor(private elRef:ElementRef) {}

   ngAfterViewInit() {
     let loader = this.elRef.nativeElement.querySelector('#loader'); 
     loader.style.display = "none"; //hide loader
  }
}

Upvotes: 3

Related Questions