Skip to content

Instantly share code, notes, and snippets.

@luchillo17
Last active September 10, 2020 15:03
Show Gist options
  • Save luchillo17/fc3d01f29580d5067541 to your computer and use it in GitHub Desktop.
Save luchillo17/fc3d01f29580d5067541 to your computer and use it in GitHub Desktop.
Showing how to make and use an Ionic 2 busy indicator with FortAwesome refresh spinner icon

#Busy indicator backup solution:

This gist show how to make a replacement for the Ionic 1 Busy indicator into Ionic 2 until the ionic staff creates the native one, relate to:

  1. Code pen ilustrating the ionic 1 version: http://codepen.io/chabelly/pen/xGdqbJ#0
  2. Ionic 1 docs about that component: http://ionicframework.com/docs/api/service/$ionicLoading/
  3. Video that shows how it looks in an ionic 2 deploy ready app, last 4 sec (hint, it is the one with spinning arrows): Ionic 2 loading replacement

##Pre-requisits You need to have linked or downloaded (most likely in mobile apps) the FortAwesome library, mostly because i use the refresh spinner icon in it.

##Install

  • Download or copy the component to the selected location, in my case the folder is in app/components/busy-component and it has 3 files, the 3 of them are listed down in this gist, however you can name it as you like, just take care of renaming the Class, the imports and everithing else:

    1. busy-component.html
    2. busy-component.js
    3. busy-component.scss
  • In app.html append at the end of file the component html selector, for example under the Nav component:

<ion-nav id="nav" [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>

<busyComponent></busyComponent>
<!-- End of file -->
  • In app.(ts|js) import the component from wherever you put it and add the controller to providers array and component to the directives array, say i put it in appFolder/app/components/busy-component then i import it into app component like:
// app.js or app.ts (In Typescript projects)
import {
  Component,
  provide,
  PLATFORM_DIRECTIVES
} from '@angular/core';
import {ionicBootstrap} from 'ionic-angular'
import {BusyComponent, BusyCtrl} from './components/busy-component/busy-component';
@Component({
  templateUrl: 'build/app.html'
})
class MyApp { ... }
ionicBootstrap(MyApp, [
  BusyCtrl,
  provide(PLATFORM_DIRECTIVES, {useValue: [BusyComponent], multi: true})
])
  • Lastly just open the component where you need it, be it injectables, components or pages, and close when you don't with the BusyCtrl.next(boolean) controller method for the component, it shows when true, and hides when false, here's an example with an injectable:
// Example for my config service: Config.js or Config.ts
import {BusyCtrl} from '../components/busy-component/busy-component';
@Injectable()
export class Config {
  // Inject the BusyCtrl in the constructor, when in js instead of ts
  // just set it without public keyword and uncomment the line inside
  // the constructor body
  constructor(
    public busyCtrl: BusyCtrl
  ) {
    // this.busyCtrl = busyCtrl
  }
  showProgress() {
    // Show busy indicator
    this.busyCtrl.next(true);
  }
  closeProgress(){
    // Hide busy indicator
    this.busyCtrl.next(false);
  }
}

Now you're ready to show and hide the busy indicator with the showProgress() and hideProgress() functions from any component you import the BusyCtrl.

##How does it work??

  1. First we have the component html, its a basic copy of the Ionic 2 alert html, the most important difference is in the expression [ngClass]="{'busy': isBusy}".
  2. Then we have the scss, this is a very important part, as we hide the component with transitions and show it only when need it, take a look about the transition of the z-index, that's very important.
  3. Lastly but the most important is the JS, take care to understand the logic, i use rxjs/subject in order to pass events from anywhere in the app to the component through the injectable, you could easily use the subscribe to pass a configuration object with the title, subTitle and message that should go in the busy component, but i keep it simple with just showing Processing in spanish and the FortAwesome refresh spinner icon.

####Note: The component uses FortAwesome (previously Font Awesome) refresh spinner as rotating icon, but you could just replace with ion-icons if you find how to make them spin.

busyComponent .container {
z-index: -1;
transition: z-index 0.2s step-end;
width: 100%;
height: 100%;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
&.busy {
z-index: 9999;
transition: z-index 0.2s step-start;
.backdrop {
opacity: 0.3;
}
.alert-wrapper {
opacity: 1;
}
}
.backdrop {
opacity: 0.01;
transition: opacity 0.2s;
}
.alert-wrapper {
opacity: 0;
transition: opacity 0.2s;
}
}
<div class="container centered" [ngClass]="{'busy': isBusy}" (click)="close()">
<div tappable disable-activated class="backdrop" role="presentation"></div>
<div class="alert-wrapper">
<div class="alert-head">
<h2 id="{{hdrId}}" class="alert-title" *ngIf="d.title" [innerHTML]="d.title"></h2>
<h3 id="{{subHdrId}}" class="alert-sub-title" *ngIf="d.subTitle" [innerHTML]="d.subTitle"></h3>
</div>
<div id="{{msgId}}" class="alert-message" *ngIf="d.message" [innerHTML]="d.message"></div>
</div>
</div>
import {Injectable, Component} from '@angular/core';
import {IONIC_DIRECTIVES} from 'ionic-angular';
import {Subject, Subscription} from 'rxjs';
@Injectable()
export class BusyCtrl {
public subject: Subject<any> = new Subject();
constructor() {}
subscribe(callback) {
return this.subject.subscribe(callback);
}
next(value) {
this.subject.next(value)
}
}
@Component({
selector: 'busyComponent',
templateUrl: 'build/components/busy-component/busy-component.html',
directives: [IONIC_DIRECTIVES] // makes all Ionic directives available to your component
})
export class BusyComponent {
public d: any = {
title: 'Processing',
subTitle: '',
message: '<i class="fa fa-refresh fa-spin fa-3x"></i>'
}
private subscription: Subscription = null
private isBusy: boolean = false
constructor(
private busyCtrl: BusyCtrl
) {
this.busyCtrl.subscribe((showIt) => {
this.isBusy = showIt
})
}
ngOnDestroy() {
this.subscription && this.subscription.unsubscribe()
}
close() {
this.isBusy = false
}
}
@kzadorlr
Copy link

Por tu nombre, voy a suponer que hablas espaniol asi que aca va la pregunta:
cuando pones " Use it in your app.html under the nav component: ", como seria exactamente? Disculpa si es una pregunta estupida pero estoy empezando Ionic 2 y, viniendo de Ionic 1, es todo muy confuso.

Desde ya, gracias.

@luchillo17
Copy link
Author

Basicamente esto en el app.html, literal justo debajo del componente de navegación:

<ion-nav id="nav" [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>
<busyComponent></busyComponent>

@keppi2
Copy link

keppi2 commented Mar 21, 2016

Think import has to be renamed to angular-ionic for beta2:
https://gist.github.com/keppi2/0cffcc1e446372e3e103/revisions

@luchillo17
Copy link
Author

@keppi2 Yes it has to, done, thanks for noticing.

@luchillo17
Copy link
Author

Updated to Angular RC versions, however i think it isn't needed any more, since Ionic 2 now has the Loading component.

@heroInCommunity
Copy link

But still Loading component does not have a function to disable it not on timeout, but at any moment as you solution has.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment