Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
[![Build Status](https://travis-ci.org/t-ho/ngx-ui-loader.svg?branch=master)](https://travis-ci.org/t-ho/ngx-ui-loader)
[![codecov](https://codecov.io/gh/t-ho/ngx-ui-loader/branch/master/graph/badge.svg)](https://codecov.io/gh/t-ho/ngx-ui-loader)
[![npm](https://img.shields.io/npm/dw/ngx-ui-loader.svg)](https://www.npmjs.com/package/ngx-ui-loader)
[![](https://data.jsdelivr.com/v1/package/npm/ngx-ui-loader/badge?style=rounded)](https://www.jsdelivr.com/package/npm/ngx-ui-loader)
[![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/ngx-ui-loader.svg)](https://bundlephobia.com/result?p=ngx-ui-loader)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![license](https://img.shields.io/npm/l/ngx-ui-loader.svg)](https://github.com/t-ho/ngx-ui-loader/wiki/License)
Expand All @@ -16,14 +15,10 @@ An all-in-one and fully customizable loader/spinner for Angular applications. It

## Features

- Support **multiple loaders** (>= ngx-ui-loader@7.1.0). See [Multiple loaders](https://tdev.app/ngx-ui-loader#multiple-loaders) for more details and [demo here](https://tdev.app/ngx-ui-loader/demo)
- Support [custom template](https://tdev.app/ngx-ui-loader#custom-template) (>= ngx-ui-loader@9.1.0).
- Support [multiple loaders](https://tdev.app/ngx-ui-loader#multiple-loaders) (>= ngx-ui-loader@7.1.0).
- Show foreground loader with **progress bar**
- The page content can be **blurred/frosted** while showing foreground loader. See [NgxUiLoaderBlurred](https://tdev.app/ngx-ui-loader#ngxuiloaderblurred-directive) directive for more details
- Show loader with different id for different tasks
- Be able to add **logo** and **loading text**
- Be able to change position of spinners, logo and loading text
- Be able to change color and size of logo, spinners and progress bar
- Be able to change the direction of progress bar
- Automatically show loader for router events. See [NgxUiLoaderRouterModule](https://tdev.app/ngx-ui-loader#automatically-show-loader-for-router-events) for more details
- Automatically show loader for http requests. See [NgxUiLoaderHttpModule](https://tdev.app/ngx-ui-loader#automatically-show-loader-for-http-requests) for more details

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"prettier": "prettier --write \"**/*.{scss,ts,component.html}\"",
"start": "ng serve",
"build": "ng build ngx-ui-loader --prod && ng build --prod",
"build:lib": "ng build ngx-ui-loader --prod && cp README.md CHANGELOG.md LICENSE ./dist/ngx-ui-loader/",
"build:lib": "ng build ngx-ui-loader --prod && cp README.md CHANGELOG.md ./dist/ngx-ui-loader/",
"build:schematics": "cd projects/ngx-ui-loader && npm run build && cd ../..",
"test": "ng test ngx-ui-loader --code-coverage",
"lint": "ng lint",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,19 @@ import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';

import { NgxUiLoaderService } from './ngx-ui-loader.service';
import { coerceNumber } from '../utils/functions';
import { ShowEvent } from '../utils/interfaces';
import { FOREGROUND, OVERLAY_DISAPPEAR_TIME, FAST_OVERLAY_DISAPPEAR_TIME } from '../utils/constants';

@Directive({ selector: '[ngxUiLoaderBlurred]' })
export class NgxUiLoaderBlurredDirective implements OnInit, OnDestroy {
private blurNumber: number;

@Input()
get blur(): number {
return this.blurNumber;
}

set blur(value: number) {
this.blurNumber = coerceNumber(value, this.loader.getDefaultConfig().blur);
}

@Input() blur: number;
@Input() loaderId: string;

showForegroundWatcher: Subscription;
fastFadeOut: boolean;

constructor(private elementRef: ElementRef, private renderer: Renderer2, private loader: NgxUiLoaderService) {
this.blurNumber = this.loader.getDefaultConfig().blur;
this.blur = this.loader.getDefaultConfig().blur;
this.loaderId = this.loader.getDefaultConfig().masterLoaderId;
this.fastFadeOut = this.loader.getDefaultConfig().fastFadeOut;
}
Expand All @@ -39,7 +28,7 @@ export class NgxUiLoaderBlurredDirective implements OnInit, OnDestroy {
.pipe(filter((showEvent: ShowEvent) => this.loaderId === showEvent.loaderId))
.subscribe(data => {
if (data.isShow) {
const filterValue = `blur(${this.blurNumber}px)`;
const filterValue = `blur(${this.blur}px)`;
this.renderer.setStyle(this.elementRef.nativeElement, '-webkit-filter', filterValue);
this.renderer.setStyle(this.elementRef.nativeElement, 'filter', filterValue);
} else {
Expand Down
10 changes: 8 additions & 2 deletions projects/ngx-ui-loader/src/lib/core/ngx-ui-loader.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@
[style.height.px]="fgsSize"
[style.top]="spinnerTop"
>
<div [class]="fgSpinnerClass">
<div *ngIf="!fgsTemplate; else foregroundTemplate" [class]="fgSpinnerClass">
<div *ngFor="let div of fgDivs"></div>
</div>
<ng-template #foregroundTemplate>
<ng-container *ngTemplateOutlet="fgsTemplate"></ng-container>
</ng-template>
</div>
<!-- Foreground spinner }}} -->

Expand All @@ -68,8 +71,11 @@
[style.color]="bgsColor"
[style.opacity]="bgsOpacity"
>
<div [class]="bgSpinnerClass">
<div *ngIf="!bgsTemplate; else backgroundTemplate" [class]="bgSpinnerClass">
<div *ngFor="let div of bgDivs"></div>
</div>
<ng-template #backgroundTemplate>
<ng-container *ngTemplateOutlet="bgsTemplate"></ng-container>
</ng-template>
</div>
<!-- Background spinner }}} -->
Original file line number Diff line number Diff line change
Expand Up @@ -327,19 +327,6 @@ describe('NgxUiLoaderComponent', () => {
expect(textEl.style.top).toBe('initial');
});

it('#validate', () => {
spyOn(console, 'error');
component.bgsPosition = 'invalid-position' as PositionType;
component.ngOnChanges({
bgsPosition: new SimpleChange(null, component.bgsPosition, true)
});
fixture.detectChanges();
expect(console.error).toHaveBeenCalledWith(
`[ngx-ui-loader] - bgsPosition ("invalid-position") is invalid. ` + `Default value "${component.defaultConfig.bgsPosition}" is used.`
);
expect(component.bgsPosition).toBe(component.defaultConfig.bgsPosition);
});

it(`start() - 1 - condition: 0 background and 0 foreground`, () => {
loaderService.start();
fixture.detectChanges();
Expand Down
47 changes: 5 additions & 42 deletions projects/ngx-ui-loader/src/lib/core/ngx-ui-loader.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
SimpleChange,
OnDestroy,
ChangeDetectionStrategy,
ChangeDetectorRef
ChangeDetectorRef,
TemplateRef
} from '@angular/core';
import { DomSanitizer, SafeResourceUrl, SafeStyle } from '@angular/platform-browser';
import { NgxUiLoaderService } from './ngx-ui-loader.service';
Expand All @@ -16,10 +17,9 @@ import { filter } from 'rxjs/operators';

import { NgxUiLoaderConfig } from '../utils/interfaces';
import { DirectionType, PositionType, SpinnerType } from '../utils/types';
import { POSITION, PB_DIRECTION, SPINNER } from '../utils/enums';
import { POSITION } from '../utils/enums';
import { SPINNER_CONFIG } from '../utils/constants';
import { ShowEvent } from '../utils/interfaces';
import { coerceNumber } from '../utils/functions';

@Component({
selector: 'ngx-ui-loader',
Expand All @@ -32,10 +32,12 @@ export class NgxUiLoaderComponent implements OnChanges, OnDestroy, OnInit {
@Input() bgsOpacity: number;
@Input() bgsPosition: PositionType;
@Input() bgsSize: number;
@Input() bgsTemplate: TemplateRef<any>;
@Input() bgsType: SpinnerType;
@Input() fgsColor: string;
@Input() fgsPosition: PositionType;
@Input() fgsSize: number;
@Input() fgsTemplate: TemplateRef<any>;
@Input() fgsType: SpinnerType;
@Input() gap: number;
@Input() loaderId: string;
Expand Down Expand Up @@ -116,12 +118,8 @@ export class NgxUiLoaderComponent implements OnChanges, OnDestroy, OnInit {
this.ngxService.bindLoaderData(this.loaderId);
this.determinePositions();

this.bgsPosition = this.validate('bgsPosition', this.bgsPosition, POSITION, this.defaultConfig.bgsPosition) as PositionType;

this.trustedLogoUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(this.logoUrl);

this.pbDirection = this.validate('pbDirection', this.pbDirection, PB_DIRECTION, this.defaultConfig.pbDirection) as DirectionType;

this.showForegroundWatcher = this.ngxService.showForeground$
.pipe(filter((showEvent: ShowEvent) => this.loaderId === showEvent.loaderId))
.subscribe(data => {
Expand Down Expand Up @@ -161,42 +159,24 @@ export class NgxUiLoaderComponent implements OnChanges, OnDestroy, OnInit {
}

const bgsTypeChange: SimpleChange = changes.bgsType;
const bgsPositionChange: SimpleChange = changes.bgsPosition;
const fgsTypeChange: SimpleChange = changes.fgsType;
const loaderIdChange: SimpleChange = changes.loaderId;
const logoUrlChange: SimpleChange = changes.logoUrl;
const pbDirectionChange: SimpleChange = changes.pbDirection;

if (fgsTypeChange || bgsTypeChange) {
this.initializeSpinners();
}

if (loaderIdChange) {
this.ngxService.updateLoaderId(loaderIdChange.previousValue, this.loaderId);
}

this.determinePositions();

if (bgsPositionChange) {
this.bgsPosition = this.validate('bgsPosition', this.bgsPosition, POSITION, this.defaultConfig.bgsPosition) as PositionType;
}

if (logoUrlChange) {
this.trustedLogoUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(this.logoUrl);
}

if (pbDirectionChange) {
this.pbDirection = this.validate('pbDirection', this.pbDirection, PB_DIRECTION, this.defaultConfig.pbDirection) as DirectionType;
}
}

/**
* Initialize spinners
*/
private initializeSpinners(): void {
this.fgsType = this.validate('fgsType', this.fgsType, SPINNER, this.defaultConfig.fgsType) as SpinnerType;
this.bgsType = this.validate('bgsType', this.bgsType, SPINNER, this.defaultConfig.bgsType) as SpinnerType;

this.fgDivs = Array(SPINNER_CONFIG[this.fgsType].divs).fill(1);
this.fgSpinnerClass = SPINNER_CONFIG[this.fgsType].class;
this.bgDivs = Array(SPINNER_CONFIG[this.bgsType].divs).fill(1);
Expand All @@ -207,11 +187,6 @@ export class NgxUiLoaderComponent implements OnChanges, OnDestroy, OnInit {
* Determine the positions of spinner, logo and text
*/
private determinePositions(): void {
this.fgsPosition = this.validate('fgsPosition', this.fgsPosition, POSITION, this.defaultConfig.fgsPosition) as PositionType;
this.logoPosition = this.validate('logoPosition', this.logoPosition, POSITION, this.defaultConfig.logoPosition) as PositionType;
this.textPosition = this.validate('textPosition', this.textPosition, POSITION, this.defaultConfig.textPosition) as PositionType;
this.gap = coerceNumber(this.gap, this.defaultConfig.gap);

this.logoTop = 'initial';
this.spinnerTop = 'initial';
this.textTop = 'initial';
Expand Down Expand Up @@ -267,18 +242,6 @@ export class NgxUiLoaderComponent implements OnChanges, OnDestroy, OnInit {
}
}

private validate(inputName: string, value: string, validTypeObj: {}, fallbackValue: string): string {
if (
Object.keys(validTypeObj)
.map(k => validTypeObj[k])
.findIndex(v => v === value) === -1
) {
console.error(`[ngx-ui-loader] - ${inputName} ("${value}") is invalid. ` + `Default value "${fallbackValue}" is used.`);
return fallbackValue;
}
return value;
}

/**
* On destroy event
*/
Expand Down
Loading