Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ionic 3 angular 4 http interceptor to show loading on every request

I'm trying to make a custom http interceptor which will be used to handle loading and other additional functions. (handling loading for each request manually significantly increasing the amount of code).

The problem is: Loader is getting activated on each request, but loading.dismiss() is not working.(Loading spinner keeps being active, no errors)

My config:

http interceptor:

@Injectable()
export class MyHttpWrapper extends Http {
  private loading: any;

  constructor(connectionBackend: ConnectionBackend, requestOptions: RequestOptions,private loadingCtrl: LoadingController) {
    super(connectionBackend, requestOptions);
  }

  public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    this.showLoader();

    return super.get(url, this.getRequestOptionArgs(options))
      .finally<Response>(() => {
        this.hideLoader();
      });
  }

  public post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
      return super.post(url, body, options);
  }

  public put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
    return super.put(url, body, options);
  }

  public delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return super.delete(url, options);
  }


  private getRequestOptionArgs(options?: RequestOptionsArgs) : RequestOptionsArgs {
    if (options == null) {
      options = new RequestOptions();
    }
    if (options.headers == null) {
      options.headers = new Headers();
    }
    options.headers.append('Content-Type', 'application/json');

    return options;
  }


  private showLoader() {
    if(!this.loading){
      this.loading = this.loadingCtrl.create({
        dismissOnPageChange: true
      });
    }
    this.loading.present();
    console.log('show loader')
  }
  private hideLoader() {
    console.log('hide loader')
    console.log(this.loading)
    this.loading.dismiss();
  }
}

app.module.ts

export function httpInterceptorFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions, loadingCtrl: LoadingController) {
  return new MyHttpWrapper(xhrBackend, requestOptions, loadingCtrl);
}
    @NgModule({
      declarations: [
        MyApp
      ],
      imports: [
        BrowserModule,
        HttpModule,
        IonicModule.forRoot(MyApp),
        IonicStorageModule.forRoot()
      ],
      bootstrap: [IonicApp],
      entryComponents: [
        MyApp
      ],
      providers: [
        StatusBar,
        SplashScreen,
        {provide: ErrorHandler, useClass: IonicErrorHandler},
        {provide: APP_CONFIG, useValue: AppConfig},
        {
          provide: Http,
          useFactory: httpInterceptorFactory,
          deps: [XHRBackend, RequestOptions, LoadingController]
        }
      ]
    })
    export class AppModule {}

UPDATE:

tried to add simple service(and use it in MyHttpWrapper), doesn't change anything, same problem.

@Injectable()
export class LoadingService {
  private loading:any;

  constructor(private loadingCtrl: LoadingController) {

  }

  show() {
    if(!this.loading){
      this.loading = this.loadingCtrl.create({
        dismissOnPageChange: true
      });
    }
    this.loading.present();
  }
  hide() {
    if (this.loading) {
      this.loading.dismiss();
    }
  }
}
like image 530
user1935987 Avatar asked Aug 01 '17 05:08

user1935987


1 Answers

I'm using the below custom HTTP interceptor on my Ionic 3 apps

This is the loader.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import { LoadingController } from 'ionic-angular';

@Injectable()
export class LoaderProvider {

  constructor(public http: Http, public loadingCtrl: LoadingController) {

  }

  loading: any = this.loadingCtrl.create({
    content: "Please wait..."
  })

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

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


}

This is the HTTP interceptor

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';

import { LoaderProvider } from '../loader/loader';

/*

Ionic 3 HTTP interceptor
Author: iSanjayAchar (@iSanjayAchar) <[email protected]>

*/

@Injectable()

export class httpService {

  baseUrl: string = 'https://yourbaseurl.in'

  constructor(public http: Http, private loader: LoaderProvider) {

  }

  get(url) {
    this.loader.show();
    return this.http.get(this.baseUrl + url)
      .map(resp => resp.json())
      .finally(() => {
        this.loader.hide();
      });
  }

  post(url, body) {
    this.loader.show();
    return this.http.post(this.baseUrl + url, body)
      .map(resp => resp.json())
      .finally(() => {
        this.loader.hide();
      });
  }

  put(url, body) {
    this.loader.show();
    return this.http.put(this.baseUrl + url, body)
      .map(resp => resp.json())
      .finally(() => {
        this.loader.hide();
      });
  }

  delete(url) {
    this.loader.show();
    return this.http.delete(this.baseUrl + url)
      .map(resp => resp.json())
      .finally(() => {
        this.loader.hide();
      });
  }

  patch(url, body) {
    this.loader.show();
    return this.http.patch(this.baseUrl + url, body) 
      .map(resp => resp.json())
      .finally(() => {
        this.loader.hide();
      });
  }
}

Now finally import this instead of http everywhere, example below

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Http, Headers, RequestOptions } from '@angular/http';
import { ToastController } from 'ionic-angular';
import 'rxjs/add/operator/map';
import { AlertController } from 'ionic-angular';
import { httpService } from '../../providers/http/http';

/**
 * Generated class for the LoginPage page.
 *
 * See http://ionicframework.com/docs/components/#navigation for more info
 * on Ionic pages and navigation.
 */

@IonicPage()

@Component({
  selector: 'page-login',
  templateUrl: 'login.html',
})

export class LoginPage {
  isLoginIn: boolean = false;

  user: any = {
    email: '',
    password: ''
  }


  constructor(private http: httpService, private toast: ToastController) {

  }

 login() {

    this.http.post('/api/v1/login/', this.user)
      .subscribe(resp => {

          //Your logic

      }, err => {

         //Your logic

      }
  }
}
like image 166
Sanjay Achar Avatar answered Oct 21 '22 15:10

Sanjay Achar