AngularJS $rootScope.$on alternative in context of migration to Angular2

1.5k views Asked by At

Our AngularJS project had start it's long way to the modern Angular.

The ngMigration util recommend me to remove all the $rootScope dependecies because Angular doesn't contain a similar concept like $rootScope. It is pretty simple in some cases but I don't know what to do with event subscription mechanisms.

For example I have a some kind of Idle watchdog:

angular
    .module('myModule')
    //...
    .run(run)

//...       
function run($rootScope, $transitions, Idle) {
    $transitions.onSuccess({}, function(transition) {
        //...
        Idle.watch(); // starts watching for idleness
    });

    $rootScope.$on('IdleStart', function() {
        //...
    });

    $rootScope.$on('IdleTimeout', function() {
        logout();
    });
}

On which object instead of $rootScope I have to call the $on function if I want to get rid of the $rootScope?

UPD

The question was not about "how to migrate on Angular2 event system". It was about how to remove a $rootScope dependencies but keep a event system. Well it seems to be impossible.

2

There are 2 answers

0
georgeawg On BEST ANSWER

I don't know what to do with event subscription mechanisms.

Angular 2+ frameworks replace the $scope/$rootScope event bus with observables.

From the Docs:

Transmitting data between components

Angular provides an EventEmitter class that is used when publishing values from a component. EventEmitter extends RxJS Subject, adding an emit() method so it can send arbitrary values. When you call emit(), it passes the emitted value to the next() method of any subscribed observer.

A good example of usage can be found in the EventEmitter documentation.

For more information, see

0
mxr7350 On

You can implement TimeOutService which will do the log out after x minutes (in this case 15 min) of inactivity or it will reset the timer after certain action(s).

import { Injectable, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, Subject, Subscription, timer } from 'rxjs';
import { startWith, switchMap } from 'rxjs/operators';

import { AuthService } from 'path/to/auth.service';

@Injectable()
export class TimeoutService implements OnDestroy {

  limitMinutes = 15;
  secondsLimit: number = this.limitMinutes * 60;
  private reset$ = new Subject();
  timer$: Observable<any>;
  subscription: Subscription;

  constructor(private router: Router,
              private authService: AuthService,
  ) {
  }

  startTimer() {
    this.timer$ = this.reset$.pipe(
      startWith(0),
      switchMap(() => timer(0, 1000))
    );
    this.subscription = this.timer$.subscribe((res) => {
      if (res === this.secondsLimit) {
        this.logout();
      }
    });
  }

  resetTimer() {
    this.reset$.next(void 0);
  }

  endTimer() {
    if (typeof this.subscription !== 'undefined') {
      this.subscription.unsubscribe();
    }

  }

  logout(): boolean {
    this.authService.signOut().subscribe((res) => {
      this.subscription.unsubscribe();
    });
    return false;
  }

  ngOnDestroy():void {
    this.subscription.unsubscribe();
  }
}

And in the AppComponent have listener which will reset timeout on certain actions

In case as bellow it listens for keyboard strokes, mouse wheel, or mouse click

 constructor(
    private timeoutService: TimeoutService
  ) {
  }

  @HostListener('document:keyup', ['$event'])
  @HostListener('document:click', ['$event'])
  @HostListener('document:wheel', ['$event'])
  resetTimer () {
    this.timeoutService.resetTimer();
  }