2

I need to setup common loader into entire angular2 project. So i just want to do is when my new http call generate either it's GET, POST, or PUT then before request sent loader is appear. Once http response(success or error) arrive from server side then loader should be disappear.

There is any in built module available using that i can do above functionality. Or give me any way so i can do it with angular functions. I am using rxjs for http request.

I not want to use jQuery or Javascript.

Jitendra Solanki
  • 343
  • 2
  • 6
  • 23

3 Answers3

2

Create http interceptor and call your common functions inside it. You may either write your own interceptor implementation like this or use an external library

Community
  • 1
  • 1
Slava.K
  • 3,073
  • 3
  • 17
  • 28
2

Extending HTTP works well - in our project we also wanted explicit control of the 'loader' aka spinner for some scenarios. So we have a SpinnerService in our Core module that is available to all components.

@Injectable()
export class SpinnerService {

  private spinnerStateSource = new Subject<SpinnerState>();
  spinnerState$ = this.spinnerStateSource.asObservable();

  private defaultMessage: string = 'Loading...';

  show(message?: string) {

    let msg = this.defaultMessage as string;
    if (message) {
      msg = message;
    }

    this.spinnerStateSource.next({ showing: true, message: msg });
  }

  hide() {
    this.spinnerStateSource.next({ showing: false, message: '' });
  }

  spin(obs: Observable<any>, message?: string): Observable<any> {
    this.show(message);
    return obs.finally(() => this.hide());
  }

}

class SpinnerState {
  showing: boolean;
  message: string;
}

A component in the main module subscribes to the service to show/hide the actual spinner UI (EDIT: just like in @Gunter's answer), and other components can (via the service) tell the spinner to show/hide.

An example where we use that is if a component has to make multiple HTTP calls to e.g. get some reference data, then we want the spinner to show til all those calls are done. So we call the spin function with the action we are waiting on

e.g. in the consuming component:

this.spinnerService.spin(
     Observable.forkJoin(
       this.refDataService.getRefDataList('statusTypes'),
       this.refDataService.getRefDataList('itemTypes')
     )
 ).subscribe(result => {
             this.statusTypes = result[0];
             this.itemTypes = result[1];
 });
Garth Mason
  • 7,611
  • 3
  • 30
  • 39
  • Here you used `SpinnerState`. What is it's default value ? I got error when i copy this code. Also what is `spinnerState$` ? – Jitendra Solanki Feb 06 '17 at 10:17
  • It's a type containing info to pass to the spinner - I've edited my post – Garth Mason Feb 06 '17 at 23:50
  • It's work fine, but i need to import this service where i use it's method. Any way to set in common ? When any HTTP request is generate it will automatic call `spinnerService.spin` method, so i not need to call this method in every request. – Jitendra Solanki Feb 08 '17 at 07:50
  • If you want it to apply to all HTTP calls by default, you'd want to extend the standard http service (as described in the linked question added by @Slava), and inject the SpinnerService there. I'd imagine both the spinner and the 'custom' http service would be defined in a Core module. – Garth Mason Feb 08 '17 at 08:00
1
@Injectable()
class MyService {
  private change:Subject<boolean> = new BehaviorSubject(false);
  public change$ = this.change.asObservable();

  constructor(private http:Http) {}

  get(...) {
    this.change.next(true)
    return this.http.get( ... )
    .map( ... )
    .finally(_ => this.change.next(false);
  }
}
@Component({
  selector: 'loader',
  template: `
  <div *ngIf="myService.change | async">is loading ...</div>
`
)}
class LoaderComponent {
  constructor(public myService:MyService){}
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567