Search code examples
angularservicecomponents

Setting a timeout in multiple components with service in angular


I'm trying to set a timeout within a set of components using angular service. I tried to follow the materials I found online but I'm a bit stuck. I already created the timeout.service.ts file and put the code there but I get multiple errors. I need help in getting this right. The timeout worked fine when it was in the component itself but I want to work according to the DRY methodology. Thanks for the support in solving this!

STACKBLITZ: https://stackblitz.com/edit/flight-date-picker-with-service

COMPONENT.TS:

    import { Component, OnInit } from '@angular/core';7
    import { Router, RouterLink } from '@angular/router';
    import { HostListener } from '@angular/core'
    import { TimeoutService } from '../timeout.service';
    
    @Component({
      selector: 'app-chooseflight',
      templateUrl: './chooseflight.component.html',
      styleUrls: ['./chooseflight.component.scss'],
      providers: [TimeoutService]
    })
    export class ChooseflightComponent implements OnInit {
      constructor(private router: Router, timeoutService: TimeoutService) {
        this.showStorage = localStorage.getItem("flightdetails") || {};
      }
    
    
      ngOnInit() {
        this.resetTimer();
      }
      // public time: any;

      // @HostListener('document:mousemove')
      // @HostListener('document:keypress')
      // @HostListener('document:click')
      // @HostListener('document:wheel')
      // resetTimer() {
      //   clearTimeout(this.time);
      //   this.time = setTimeout(() => {
      //   localStorage.removeItem("flightdetails");
      //   console.log("Local storage will now be deleted");
      //   this.router.navigate(["/chooseflight"]);
      //   }, 180000);
      // }

The commented parts were moved to the service file:

    export class TimeoutService {
      public time: number;
      
      console.log("TimeoutService Działa!");
      @HostListener('document:mousemove')
      @HostListener('document:keypress')
      @HostListener('document:click')
      @HostListener('document:wheel')
      resetTimer() {
        clearTimeout(this.time);
        this.time = setTimeout(() => {
        localStorage.removeItem("flightdetails");
        console.log("Local storage will now be deleted");
        this.router.navigate(["/chooseflight"]);
        }, 180000);
      }
    }

Solution

  • You are on the right track. However, when you copied the code to the service you missed a few important steps:

    1. Import everything you need in the service and use a constructor as you were in the component
    2. Set up a service as a provider in the app.module

    1 Import everything you need in the service and use a constructor as you were in the component

    In the service, you only have the @HostListener without the proper imports. At the top of the service.ts file, I added the following:

    import { Router } from "@angular/router";
    import { HostListener, Injectable} from "@angular/core";
    
    
    @Injectable({
      providedIn: 'root',
    })
    

    See that I also added the @Injectable({}). You can learn more about this here, here or here. The @Injectable() is an essential ingredient in every Angular service definition.

    Now inside of the class, you need to add a constructor since you plan on using a router:

    constructor(private router: Router) {  }
    

    as a sidenote,, you may need to change where the router.navigate is pointing to since you're in a different file, so make sure to check this.

    2 Set up a service as a provider in the app.module

    Any time you use a service in an app, you need to set it up as a provider in the app.module (or whichever module you are using for the app). This is a quick fix. In your app.module.ts file, at the top with the other imports, add the following:

    import { TimeoutService } from './timeout.service';` 
    

    then, in the @NgModule({...}), add a providers: [] array to hold all your services.

    @NgModule({
      imports:      ...
      ...
      providers: [TimeoutService]
    })
    

    This should now be set up as you had it before in the component. Please let me know if you have any questions. Here is the updated StackBlitz