Reputation: 9800
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
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
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
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
Reputation: 11243
First of all your implementation is pretty standard way to show the loading spinner.
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
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>
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