I’m currently working on a project using Angular2, and, as with many applications, I needed a loading indicator. After doing some research, I decided to use Spin.js, a JavaScript library that can be used to render a ‘spinner’ without using external images or CSS. I then started thinking about how to do this with Angular2; do I need a component that I put in every page? Is there a way to share a single root level component with my app? etc. I read through some blogs and other documentation and learned how to set up an observable subscription in order to control a single component using a service that you pass around your application. I think this can be a really useful pattern of development for a number of purposes, but here’s a look at how I created an Angular2 spinner component with Spin.js.
First of all, I created the component that I’ll put an instance of in my root application view.
@Component({
selector: 'ng2-spinner',
templateUrl: './app/spinner/spinner.component.html'
}) export class SpinnerComponent implements OnInit, OnDestroy {
In the component I exposed the Spin.js options as Angular2 component inputs
@Input() lines: number = 12; // The number of lines to draw @Input() length: number = 20; // The length of each line @Input() width: number = 12; // The line thickness @Input() radius: number = 50; // The radius of the inner circle @Input() scale: number = 1.0; // Scales overall size of the spinner ...
Then on the component’s ngOnInit callback I initialized the component with a setup of inputs from the view specifying spin.js options. It’s important to do so in the ngOnInit callback because doing so in the constructor would be too early. The inputs would not yet be passed from the parent view element.
ngOnInit() {
this.initSpinner(); this.createServiceSubscription();
}
private initSpinner() {
let options = {
lines: this.lines, length: this.length, width: this.width, radius: this.radius, scale: this.scale, corners: this.corners, color: this.color, opacity: this.opacity, rotate: this.rotate, direction: this.direction, speed: this.speed, trail: this.trail, fps: this.fps, zIndex: 2e9, // Artificially high z-index to keep on top className: this.className, top: this.top, left: this.left, shadow: this.shadow, hwaccel: this.hwaccel, position: this.position
}; console.log('Creating spinner with options:'); console.log(JSON.stringify((options))); this.spinner = new Spinner(options);
}
Now there is an instance of the spin.js object created that can be shown and hidden as needed. Next comes the magic, you need to create a service that holds a shared observable in order to control the spinner component from other components within the application. Note: it’s important to import the Rxjs ‘share’ operator in order to create the shared observable, I did so in a file called rxjs-operators.ts that I’ve imported into my main application component.
@Injectable() export class SpinnerService {
private spinnerObserver: Observer; public spinnerObservable: Observable;
constructor() {
this.spinnerObservable = new Observable(observer => {
this.spinnerObserver = observer;
}
).share();
}
}
The spinner component can then subscribe to this observable. It will be able to receive notifications from the service telling it whether it should show or hide the spinner. I’ve also called this subscription code from within the ngOnInit callback, though it’d be fine to do so within the component constructor as well.
private createServiceSubscription() {
this.subscription =
this.spinnerService.spinnerObservable.subscribe(show => {
if (show) {
this.startSpinner();
} else {
this.stopSpinner();
}
});
}
The service can use the observable in order to trigger the show and hide states in the component.
show() {
if (this.spinnerObserver) {
this.spinnerObserver.next(true);
}
}
hide() {
if (this.spinnerObserver) {
this.spinnerObserver.next(false);
}
}
Now I can drop an instance of my spinner component in my main app component specifying its view options:
<ng2-spinner [radius]="25" [lines]="15" [width]="8" [length]="15" [opacity]="0.1" [shadow]="true"></ng2-spinner>
And pass around the spinner service to control showing/hiding it everywhere else in my application
constructor(private spinnerService: SpinnerService) { }
public spin(event: MouseEvent): void {
event.preventDefault(); this.spinnerService.show(); setTimeout(() => {
this.spinnerService.hide();
}, 1000);
}
I think this is a really useful pattern and can imagine it’ll come in handy on future projects.
You can check out my demo project with the full code listings at:
https://github.com/seanlmcgill/ng2spin
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
Cookie | Duration | Description |
---|---|---|
cookielawinfo-checbox-analytics | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics". |
cookielawinfo-checbox-functional | 11 months | The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional". |
cookielawinfo-checbox-others | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other. |
cookielawinfo-checkbox-necessary | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary". |
cookielawinfo-checkbox-performance | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance". |
viewed_cookie_policy | 11 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data. |
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.