Loader/spinner?

These have been added in beta 2

<ion-spinner></ion-spinner>
1 Like

Hi Mike. I was more referring to a version of $ionicLoading.

Ahh alright! The Loading service is targeted for beta 7, so a little ways off for now.

I just put up the code for the loading component I created (based on Luchillo’s) if anyone wants to use it until the real loading service is implemented: http://www.joshmorony.com/how-to-create-a-custom-loading-component-in-ionic-2/

2 Likes

You can create custom component. For example:
spinner.scss

spinner {
  position: relative;
  display: inline-block;
  &.middle {
    width: 5rem;
    height: 5rem;
  }
  &.center {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
  }
  .circle {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    border-radius: 50%;
    animation: rotation 1.2s linear infinite;
    &.inside {
      border: 0.4rem solid red;
      width: 65%;
      height: 65%;
      border-left-color: transparent;
      border-right-color: transparent;
      animation-direction: reverse;
    }
    &.outside {
      border: 0.5rem solid orange;
      width: 100%;
      height: 100%;
      border-left-color: transparent;
      border-right-color: transparent;
    }
  }
}

@keyframes rotation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

spinner.ts

import {Component} from 'angular2/core';

@Component({
  selector: 'spinner',
  templateUrl: 'build/components/spinner/spinner.html',
})
export class SpinnerComponent {

  constructor() {}
}

spinner.html

<div class="circle inside"></div>
<div class="circle outside"></div>

How use?
Added to your html

<spinner class="middle center"></spinner>

Added directive

directives: [SpinnerComponent]

Ready :slight_smile:

Update: Little css fix (removed useless property)

3 Likes

Hey guys, this is a really great discussion and it’s good to see everyone’s custom solutions.

But it looks Loading is now officially supported in the latest Ionic2:

Here’s a snippet taken from the documentation showing its usage:

  let loading = Loading.create({
    content: 'Please wait...'
  });

  this.nav.present(loading);
1 Like

How loading can be used in subscribe when logging in? Any example code would be appreciated. Thanks

Give this a try. It is just the essential stuff. Let me know if you have any question.

Login.ts

import {Component} from '@angular/core';
import {Loading, NavController} from 'ionic-angular';
import {MainPage} from '../../main-page/main-page';
import {Auth} from '../../../providers/auth/auth';

@Component({
  templateUrl: 'build/pages/login/loginPage/loginPage.html',
  providers: [Auth]
})
export class LoginPage {
  loading: any;
  constructor(public nav: NavController, public auth: Auth){
   this.loading = Loading.create({
      content: 'Authenticating...'
    });
  }

login() {
    this.nav.present(this.loading);
    this.auth.login(this.loginForm.value)
      .subscribe((data) => {
        if (data) {
          this.loading.dismiss();
          console.log('the data is: ', data);
          this.nav.setRoot(MainPage);
        }
      }, (err) => {        
          this.loading.dismiss();
          console.log('an error has occurred:', err);
      });
     }
};
1 Like

How do we style the Loading?
In ionic 1, I used the $ionicLoading with a css .

spinner svg {
width: 30px;
height: 30px;
stroke: greenyellow;
fill: greenyellow;
}

This does not work in Ionic 2.
Do you know how to do styling for Loading component
?

I’m using the Loading.create
but when I’m try to run ionic serve, It always give me an error
Error TS2341: Property 'create' is private and only accessible within class 'Loading'

*I already call Loading in this line import { Loading,NavController,NavParams } from 'ionic-angular';

Any help apriciated :smiley:

You are most likely using a recent version of ionic. Loading.create is now deprecated and LoadingController should be used instead. Refer to the code below:

import { LoadingController } from 'ionic-angular';

export class MyPage {
  constructor(public loadingCtrl: LoadingController) {
  }

  presentLoading() {
    let loader = this.loadingCtrl.create({
      content: "Please wait...",
      duration: 3000
    });
    loader.present();
  }
}
1 Like

Thank You… Your Right :smiley: Error of the Loading.Create has been gone…

But, I’m still got 1 issue…

I got error in this code this.navCtrl.present(this.loading);

And the error says present does not exist on navCtrl

Is there’s any change on the new version ??

You are very close. Refer to the code I posted:

loader.present();

Just use loader.present instead of navCtrl.present.

Thank You Very much sir :smiley:

But, I don’t understand.
I already use the code onPageWillEnter() But still get error Undefined Variable on my console… (testing the app on browser)

I think, the app still render the page first rather waiting my promises finish the job… (because I can see the data that I want from the promises and the position of it is below the error on console)…

How to Fix this ??

Here’s the console look like…

I’m getting a Cannot read property 'nativeElement' of null error when navigating to tabs that try to present a loader (see issue #6209). What’s the proper way to prevent loader presentation from conflicting with other nav events? A comment in issue 7449 mentions chaining promises, but that doesn’t seem to match the current LoadingController docs, and I have no idea how to hijack tab navigation events.

Thanks, i got this working.
But this will be for available for 3 seconds, i want it hide automatically once requested data is available.

How to manage hide/show loading based on once data is available after successful HTTP request?

You call dismiss in the subscribe clause.

Hello all,
i got this working finally.
Below is my code.

import { Component, OnInit } from '@angular/core';
import { AlertController, LoadingController } from 'ionic-angular';
import { Router } from '@angular/router';
import { User } from '../../models/User';
import { UserService } from '../../providers/UserService';

@Component({
  selector: 'page-Login',
  templateUrl: 'Login.html'
})
export class Login implements OnInit {
  user: User = <User>{};
  loading: any;

  constructor(public router: Router,
    public userService: UserService,
    public alertCtrl: AlertController,
    public loadingCtrl: LoadingController) {
  }

  ngOnInit(): void {
  }

  showLoading() {
    this.loading = this.loadingCtrl.create({
      content: 'Please wait..'
    });
    this.loading.present();
  }

  hideLoading() {
    this.loading.dismiss();
  }

  showAlert(Title: string, Message: string) {
    let alert = this.alertCtrl.create({
      title: Title,
      subTitle: Message,
      buttons: ['OK']
    });
    alert.present();
  }

  // Attempt to login in through our userService service
  Login() {
    if (navigator.onLine) {
      this.showLoading();
      this.userService.login(this.user.Username, this.user.Password).then(
        (res) => {
          this.hideLoading();
          localStorage.setItem('User', JSON.stringify(this.userService.user));
          this.router.navigate(['/Orders']);
        },
        (err) => {
          this.hideLoading();
          this.showAlert(err.statusText, JSON.parse(err._body).error);
        });
    }
    else {
      this.showAlert('אין חיבור רשת', 'נא לבדוק את חיבור האנטרנט או חבילת הנתונים');
    }
  }
}

Sharing is caring… :slight_smile:

I think storing loading components in object properties is a bad idea for two reasons: (a) it blurs the line of who’s responsible for dismissing them and (b) it facilitates accidental reuse (which will blow up in your face). I recommend always making them lexically scoped instead.

1 Like

Currently, I’m doing this, motivated more by a desire to keep the user entertained than any programming reason. Interested in people’s thoughts.

I have a file loading-messages inside my providers folder, since the database and auth services are the ones that use loading spinners. Inside loading-messages are classes like

export class CreatingAccountLoadingMessage {
  loading: Loading;
   constructor(loadCtrl: LoadingController) {
     this.loading = loadCtrl.create({content:'Creating new account...'});
   }

   present() {
     this.loading.present();
   }

   dismiss() {
     this.loading.dismiss();
   }
}

There is a lot of code duplication here, as most classes are identical except for the text of the loading message. The justification for this is that it improves readability of the code where it is used. Example:

    createNewAccountMethod() {
       let createAccountSpinner = new CreatingAccountLoadingMessage(this.loadCtrl);
       createAccountSpinner.present();
       somePromiseThatResolvesWhenAccountIsCreated
            .then(resolve => {createAccountSpinner.dismiss(); other computation});
    }

That way, it’s easy to drop different loading spinners into different Promises and subscriptions, and easy to read the code also.