I’m trying to make a webpage using Angular 17 that opens into a ‘loading screen’ div positioned above the other elements, and the div disappears after two seconds. The timer is controlled using setTimeout(). It sort of works, except the main content is still visible for a second before the loading screen pops up.
app.component.html
<div *ngIf = "LoadingStatus" class = "LoadingScreen">
<!-- div displays loading screen for two seconds upon opening, then disappears. -->
</div>
<!-- <ng-container *ngIf = "!LoadingStatus"> -->
<div class = "background">
<div id = pLogo>
<!-- main content -->
</div>
</div>
<router-outlet />
<!-- </ng-container> -->
app.component.ts
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ButtonModule } from 'primeng/button';
import { DividerModule } from 'primeng/divider';
import { RippleModule } from 'primeng/ripple';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, ButtonModule, DividerModule, RippleModule, CommonModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit{
title = 'login_app';
LoadingStatus = true;
ngOnInit(): void {
setTimeout(() => {
this.LoadingStatus = false;
}, 2000);
}
}
app.component.css
h1, h2, h3, p {
font-family: "Arial";
}
#pLogo {
position: fixed;
top: 20px;
left: 20px;
}
.background {
background-color: #ffffff;
height: 100vh;
width: 45%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
#welcomeText {
margin-top: 25%;
}
#loginButton {
margin-top: 15%;
}
#RequestAccessLink {
margin-top: auto;
margin-bottom: 10%;
}
:host ::ng-deep .p-button {
background-color: #00a19c;
border-color: #00a19c;
font-family: Arial, sans-serif !important;
font-size: 1.5vw;
}
:host ::ng-deep .p-button:hover {
background-color: #00928d;
border-color: #00928d;
font-family: Arial, sans-serif !important;
font-size: 1.5vw;
}
.LoadingScreen {
background-color: #00a19c;
height: 100vh;
width: 100vw;
margin:0px;
position: fixed;
z-index: 1000;
}
What could the issue be?
Thank you!
A simpler option is to use afterNextRender
to trigger the flag only on the browser.
This behaves the same as defer
and only run on the browser.
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, ButtonModule, DividerModule, RippleModule, CommonModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit{
title = 'login_app';
LoadingStatus = true;
ngOnInit(): void {
afterNextRender(() => {
setTimeout(() => {
this.LoadingStatus = false;
}, 2000);
});
}
}
I think you have SSR enabled, because of this the main content is visible and causes the flash.
You can use @defer
to render the content only on the browser, which gets rid of this.
This is the concept, feel free to adjust the placement of the defer
to suit your requirements, you might want to warp it on the main content.
@defer() {
<div *ngIf = "LoadingStatus" class = "LoadingScreen">
<!-- div displays loading screen for two seconds upon opening, then disappears. -->
</div>
<!-- <ng-container *ngIf = "!LoadingStatus"> -->
<div class = "background">
<div id = pLogo>
<!-- main content -->
</div>
</div>
<router-outlet />
<!-- </ng-container> -->
}