Creating an Angular Component Library - Overlay Loader Component
Published on
Another simple component we can build for our library is a overlay loader component. This is a component you might use when first loading a page or loading new data for a page and want to disable the entire screen while the page/data is loading.
Prerequisites
- Install Node
- Install Angular CLI
- Creating an Angular Component Library - Workspace Setup
- OR Clone this github repository
Generate Our Overlay Loader
First we will generate a new module and a component for our page loader.
ng generate module components/overlay-loader --project=foo
ng generate component components/overlay-loader --project=foo
And we will update our module to export our page-loader component to make the component accessable by impoting modules.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OverlayLoaderComponent } from './overlay-loader.component';
@NgModule({
declarations: [
OverlayLoaderComponent
],
imports: [
CommonModule
],
exports: [
OverlayLoaderComponent
]
})
export class OverlayLoaderModule { }
We will also create two enums to model the overlay style and the spinner size.
touch projects/foo/src/lib/components/overlay-loader/overlay-loader-style.enum.ts
touch projects/foo/src/lib/components/overlay-loader/spinner-size.enum.ts
We going to create quite a few different overlay styles. Our enum will look something like this…
export enum OverlayLoaderStyle {
TRANSPARENT = 'overlay-loader-style-transparent',
DIM_DARK = 'overlay-loader-style-dim-dark',
DIM_LIGHT = 'overlay-loader-style-dim-light',
PRIMARY = 'overlay-loader-style-primary',
SECONDARY = 'overlay-loader-style-secondary',
SUCCESS = 'overlay-loader-style-success',
INFO = 'overlay-loader-style-info',
WARNING = 'overlay-loader-style-warning',
DANGER = 'overlay-loader-style-danger'
}
And our spinenr size enum…
export enum SpinnerSize {
SMALL = 'spinner-size-sm',
MEDIUM = 'spinner-size-md',
LARGE = 'spinner-size-lg'
}
Now we can update our components
directory’s public_api.ts
file…
// Overlay Loader
export * from './overlay-loader/overlay-loader.component';
export * from './overlay-loader/overlay-loader.module';
export * from './overlay-loader/spinner-size.enum';
export * from './overlay-loader/overlay-loader-style.enum';
Creating Our Overlay Loader
Our overylay loader component will be made up of an overlay div fixed across the full width and height of the screen. Inside we will also have a circular spinner indicating that the page is loading. Its a pretty simple HTML structure and will look something like this…
<div class="overlay-loader">
<div class="overlay" [@fadeInOut] *ngIf="isLoading" [ngClass]="overlayStyle">
<div class="spinner">
<div class="spinner-inner" [ngClass]="spinnerSize"></div>
</div>
</div>
<div class="content" [@fadeInOut] *ngIf="!isLoading">
<ng-content></ng-content>
</div>
</div>
Our SCCS styles…
@import '../_shared/scss/variables';
@mixin generate-spinner-by-size($size, $borderWidth) {
border-width: $borderWidth;
width: $size;
height: $size;
}
@mixin generate-overlay-style($color, $spinner, $track) {
background: $color;_
.spinner {
.spinner-inner{
border-color: $track;
border-top-color: $spinner;
}
}
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.overlay-loader {
position: relative;
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 100;
.spinner {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -80%);
.spinner-inner {
border-radius: 50%;
border-style: solid;
animation: spin 0.75s linear infinite;
&.spinner-size-sm {
@include generate-spinner-by-size(72px, 9px);
}
&.spinner-size-md {
@include generate-spinner-by-size(96px, 12px);
}
&.spinner-size-lg {
@include generate-spinner-by-size(128px, 16px);
}
}
}
&.overlay-loader-style-transparent {
background: transparent;
.spinner {
.spinner-inner{
border-color: #FFF;
border-top-color: #2b3e50;
}
}
}
&.overlay-loader-style-dim-dark {
@include generate-overlay-style(
rgba(#000, 0.3), $primary, darken(#FFF, 20%));
}
&.overlay-loader-style-dim-light {
@include generate-overlay-style(
rgba(#FFF, 0.5), $primary, lighten($primary, 20%));
}
&.overlay-loader-style-primary {
@include generate-overlay-style(
$primary, darken($primary, 10%), lighten($primary, 20%));
}
&.overlay-loader-style-secondary {
@include generate-overlay-style(
$secondary, darken($secondary, 10%), lighten($secondary, 20%));
}
&.overlay-loader-style-success {
@include generate-overlay-style(
$success, darken($success, 10%), lighten($success, 20%));
}
&.overlay-loader-style-info {
@include generate-overlay-style(
$info, darken($info, 10%), lighten($info, 20%));
}
&.overlay-loader-style-warning {
@include generate-overlay-style(
$warning, darken($warning, 10%), lighten($warning, 20%));
}
&.overlay-loader-style-danger {
@include generate-overlay-style(
$danger, darken($danger, 10%), lighten($danger, 20%));
}
}
}
And our component class file which has a few @Input
decorators for configuration values…
import { Component, OnInit, Input } from '@angular/core';
import { SpinnerSize } from './spinner-size.enum';
import { OverlayLoaderStyle } from './overlay-loader-style.enum';
import { FADE_IN_OUT } from '../_shared/animations/fade-in-out.animation';
@Component({
selector: 'foo-overlay-loader',
templateUrl: './overlay-loader.component.html',
styleUrls: ['./overlay-loader.component.scss'],
animations: [FADE_IN_OUT]
})
export class OverlayLoaderComponent implements OnInit {
@Input()
public isLoading: boolean;
@Input()
public overlayStyle: OverlayLoaderStyle;
@Input()
public spinnerSize: SpinnerSize;
constructor() {
this.spinnerSize = SpinnerSize.MEDIUM;
this.overlayStyle = OverlayLoaderStyle.DIM_DARK;
this.isLoading = false;
}
ngOnInit(): void {
}
}
One thing you will notice about our component class file is we using another shared animation, FADE_IN_OUT
, which we still need to create. It’s a basic fade in/out animation that we will probably use elsewhere in our library. We should add this to our _shared/animations
directory for reuse later.
First we need to create our file…
touch projects/foo/src/lib/components/_shared/animations/fade-in-out.animation.ts
And our fade in/out animation…
import { trigger, style, animate, transition } from '@angular/animations';
export const FADE_IN_OUT = trigger('fadeInOut', [
transition(':enter', [
style({ opacity: 0 }),
animate('0.1s', style({ opacity: 1 }))
]),
transition(':leave', [
style({ opacity: 1 }),
animate('0.1s', style({ opacity: 0 }))
])
])
Using Our Overlay Loader Component
Using our overlay loader component is pretty straight forward. We can wrap our page content in an <foo-overlay-loader>
element passing in any configuration values we want.
<foo-overlay-loader
[overlayStyle]="OverlayLoaderStyle.DIM_DARK"
[spinnerSize]="SpinnerSize.SMALL"
[isVisible]="isVisible">
<!-- ADDITIONAL HTML PAGE CONTENT HERE -->
</foo-overlay-loader>
Changing the isVisible
value will toggle the loader on and off.
Now we can build our library with npm run build
.
Stackblitz Result
I’ve also embeded a Stackblitz showing our overlay loader being used with our dashabord layout we create a few posts back. As you navigate to different pages using the side navigation, you will see a our overlay loader being display prior to displaying the page. A setTimeout
is used to simulate loading data.
The completed github repository can be found here
More Posts
- Creating an Angular Component Library - Workspace Setup
- Creating an Angular Component Library - Alert Component
- Creating an Angular Component Library - Progress Bar Component
- Creating an Angular Component Library - Toaster Component
- Creating an Angular Component Library - Card Component
- Creating an Angular Component Library - Flip Card Component
- Creating an Angular Component Library - Overlay Loader Component
- Creating an Angular Component Library - Overlay Side Panel Component
- Creating an Angular Component Library - Button Component
- Creating an Angular Component Library - Toggle Switch Component
- Creating an Angular Component Library - Checkbox Component