Spinner for SLDS-UI Module
One more interesting use case for SLDS UI Module I want to describe is Global Spinner. I'm not sure is closing of the whole page under the Spinner on requests is good practice, but my practice shows it looks nice and is clear for users that something happens in background and they should wait.
As Global Spinner should be the singleton we need to provide some interface to interact with this component from any place in our application.
First generate component (like described here - Custom SLDS-UI Angular Module)
ng g c slds-global-spinner --module=slds-ui.module.ts --prefix="" --export=true
and service
ng g s slds-global-spinner
(move slds-global-spinner service to the component folder to make it looks better)
Add SldsGlobalSpinnerService to "providers" list in slds-iu.module.ts
slds-global-spinner.service.ts
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SldsGlobalSpinnerService {
level = 0;
private showChangeSource = new Subject<boolean>();
getShow(): Observable<boolean> {
return this.showChangeSource.asObservable();
}
showSpinner(): void {
if (this.level === 0) {
this.showChangeSource.next(true);
}
this.level++;
}
hideSpinner(): void {
this.level--;
if (this.level === 0) {
this.showChangeSource.next(false);
}
}
}
slds-global-spinner.component.ts
import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { SldsGlobalSpinnerService } from './slds-global-spinner.service';
@Component({
selector: 'slds-global-spinner',
templateUrl: './slds-global-spinner.component.html',
styleUrls: ['./slds-global-spinner.component.scss']
})
export class SldsGlobalSpinnerComponent implements OnDestroy {
show = false;
private showChangeSubscription: Subscription;
constructor(
private spinnerService: SldsGlobalSpinnerService
) {
this.showChangeSubscription = this.spinnerService.getShow().subscribe(
(val) => {
this.show = val;
}
);
}
ngOnDestroy() {
this.showChangeSubscription.unsubscribe();
}
}
slds-global-spinner.component.html
<div *ngIf="show" class="c-spinner_container">
<div class="c-spinner c-spinner-1"></div>
</div>
slds-global-spinner.service.scss
.c-spinner_container {
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
z-index: 99999;
}
.c-spinner {
position: relative;
display: inline-block;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
width: 100px;
height: 100px;
border: 2px solid #01bcd4;
border-radius: 50%;
animation: spin 0.75s infinite linear;
}
.c-spinner-1 {
border-top-width: 0;
}
.c-spinner::before,
.c-spinner::after {
left: -2px;
top: -2px;
display: none;
position: absolute;
content: '';
width: inherit;
height: inherit;
border: inherit;
border-radius: inherit;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
To make it work add this tags <slds-global-spinner></slds-global-spinner> to the end of app.component.html
Usage example in task-details.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { RemoteService } from '../services/remote.service';
import { ITask } from '../interfaces';
import { TaskService } from '../services/task.service';
import { SldsGlobalSpinnerService } from '../slds-ui/slds-global-spinner/slds-global-spinner.service';
@Component({
selector: 'app-task-details',
templateUrl: './task-details.component.html',
styleUrls: ['./task-details.component.scss']
})
export class TaskDetailsComponent implements OnInit {
task: ITask = null;
constructor(
private route: ActivatedRoute,
private router: Router,
private taskService: TaskService,
private spinnerService: SldsGlobalSpinnerService
) {}
ngOnInit() {
const taskId = this.route.snapshot.paramMap.get('id');
console.log('TASK ID:', taskId);
this.getTask(taskId);
}
async getTask(id: string) {
this.spinnerService.showSpinner();
try {
this.task = await this.taskService.getTask(id);
} catch (err) {
console.log('ERR:', err);
if (+err.status === 404) {
this.spinnerService.hideSpinner();
this.router.navigate(['/tasks']);
return;
}
throw err;
}
this.spinnerService.hideSpinner();
}
...
}
Also you can see in this example new approach to work with promises - async/await.
Now, when your remove requests start you should see this nice spinner in your page
Comments
Post a Comment