Aside from using IdleJS and ngDoCheck(), how can we detect user inactivity in Angular 5?
Thanks

- 963
- 2
- 14
- 40
-
https://stackoverflow.com/questions/54925361/how-to-give-session-idle-timeout-in-angular-6/61773199#61773199 – jagjeet May 13 '20 at 11:22
4 Answers
You could try with this :
export class AppComponent {
userActivity;
userInactive: Subject<any> = new Subject();
constructor() {
this.setTimeout();
this.userInactive.subscribe(() => console.log('user has been inactive for 3s'));
}
setTimeout() {
this.userActivity = setTimeout(() => this.userInactive.next(undefined), 3000);
}
@HostListener('window:mousemove') refreshUserState() {
clearTimeout(this.userActivity);
this.setTimeout();
}
}
Seems to work in this stackblitz : open the console, don't move your mouse for 3 seconds : you see the message.
Refresh the page, move your mouse on the preview (right side) for a couple of seconds : the message doesn't pop until you stop for 3s.
You can obviously export that into a service, because as you can see, I'm using only a class to do that.
-
-
2it works. I have just tried. awesome answer and work you have there! thank you so much! – Artanis Zeratul Aug 02 '18 at 14:15
-
I want to use a timer that runs a decreased time like activity check for 10 mins after 9 min timer should run decreasing the time but without any NPM – umang naik Apr 27 '20 at 02:45
-
3Remember that this assumes the user is using a mouse. That might not work great for mobile users, or for those using screen readers or just keyboards. – StriplingWarrior Sep 03 '20 at 23:16
-
If using small idle time values (such as a few seconds), the code above may be run outside of Angular Zone, so that it doesn't trigger changeDetection too often. – Chris Nov 28 '20 at 13:03
-
Service that solves this problem (instead of a component as the accepted answer), handles touch, type and mouse. Emits an event N seconds after the user has been idle, and when he 'wakes up'. Works on Angular 11:
import { Injectable } from "@angular/core";
import { fromEvent, Subject } from "rxjs";
@Injectable({
providedIn: 'root',
})
export class IdleService {
public idle$: Subject<boolean> = new Subject();
public wake$: Subject<boolean> = new Subject();
isIdle = false;
private idleAfterSeconds = 10;
private countDown;
constructor() {
// Setup events
fromEvent(document, 'mousemove').subscribe(() => this.onInteraction());
fromEvent(document, 'touchstart').subscribe(() => this.onInteraction());
fromEvent(document, 'keydown').subscribe(() => this.onInteraction());
}
onInteraction() {
// Is idle and interacting, emit Wake
if (this.isIdle) {
this.isIdle = false;
this.wake$.next(true);
}
// User interaction, reset start-idle-timer
clearTimeout(this.countDown);
this.countDown = setTimeout(() => {
// Countdown done without interaction - emit Idle
this.isIdle = true;
this.idle$.next(true);
}, this.idleAfterSeconds * 1_000)
}
}
Usage, inject in constructor and use:
constructor(private idleService: IdleService) {
idleService.idle$.subscribe(s => console.log('im idle, zzz'));
idleService.wake$.subscribe(s => console.log('im awake!'));
}

- 5,363
- 6
- 65
- 108

- 4,481
- 1
- 31
- 39
-
3Might be adequate to change `Subject` to `BehaviorSubject` with an initial value that represents an 'awake' state upon app start, to prevent a false 'idle' state in the subscribers of `idle$` and `wake$` when the app just starts. – Lorraine R. Nov 14 '21 at 10:21
-
2Nice addition to your solution would be to make the service get the idle duration through the constructor (passed in) rather then have it hard coded. Otherwise great work – krul Dec 30 '21 at 12:52
-
1
This solution worked fine for me. the problem I faced with the accepted answer is, it only focuses on mouse events and no keyboard keypress events
userActivity;
userInactive: Subject<any> = new Subject();
constructor( ) {
this.setTimeout();
this.userInactive.subscribe(() => {
this.router.navigate(['/auth/lock']);
});
}
These events check if user is idle for a specific time and then subscribe to a different ( lock ) screen
keyPress(event: KeyboardEvent): void { clearTimeout(this.userActivity); this.setTimeout(); } setTimeout(): void { this.userActivity = setTimeout(() => this.userInactive.next(undefined), 900000); } @HostListener('window:mousemove') refreshUserState() { clearTimeout(this.userActivity); this.setTimeout(); }

- 132
- 1
- 5
-
1I like that you take into account the keyboard activity and not just mouseevents. FYI I had to add "@HostListener('document:keydown', ['$event'])" to the keyPress event. I also used keydown instead of keypress based on the information in: https://stackoverflow.com/questions/37362488/how-can-i-listen-for-keypress-event-on-the-whole-page/37363257 – Thomas Jahncke Jan 14 '21 at 13:26
-
1I am also adding touchEvent for mobile device uses: @HostListener('touch', ['$event']) touchEvent() ... – Thomas Jahncke Jan 14 '21 at 13:37
-
2
A possible solution is to use this package angular-user-idle
I have not used it in real application but might be slightly more robust than the solution proposed in the previous answer.

- 2,561
- 1
- 24
- 34
-
This seems to work nicely and has more options than the accepted answer – John White May 08 '20 at 10:04