Easy way to make Angular 2 services configurable
There are several ways to make configurable components and services in Angular 2 / 4 - APP_INITIALIZER
, providers
, dependency injection
, etc.
But these can sometimes be confusing to use. An easy way to make your services configurable is to simply use a class setter in your service. An example can be found in the library I recently built ng-idle-timeout. (There are a couple libraries that do something similar, but were overkill for the most part)
This service is used to set the idle timeout (user has not moved mouse, typed, clicked etc for a length of time) for the UI. But obviously all consumers of the service will have different business requirements for what this length of time should be. In my library, the default is set for 20 minutes, but let's look at how to override this.
@Injectable()
export class TimeoutService {
idleTime = 1200000;
constructor() { }
handleInactivity() {
return new Observable(observer => {
let timeout;
const setInactive = () => {
observer.next(true);
};
const resetTimer = () => {
clearTimeout(timeout);
timeout = setTimeout(setInactive, this.idleTime);
};
window.onload = resetTimer;
document.onmousemove = resetTimer;
document.onmousedown = resetTimer;
document.onkeydown = resetTimer;
document.onscroll = resetTimer;
document.ontouchstart = resetTimer;
document.ontouchmove = resetTimer;
});
}
setIdleTime(idleTime: number) {
this.idleTime = idleTime;
}
}
The setIdleTime
method allows consumers to override the default timeout. Consuming this is very easy. To use this service, import it at the root module of your app (usually app.module.ts) and in your root component (usually app.component.ts) subscribe to the observer, like so:
import { TimeoutService } from '/path/to/timeout.service';
@Component({})
export class AppComponent {
constructor(private timeoutService: TimeoutService) {
this.timeoutService.setIdleTime(300000); // call this method if you want to override default 20 minute timeout
this.timeoutService.handleInactivity()
.subscribe(inactive => {
// some action here
});
}
}
You can implement this on an individual component if you wish, but as the root component is instantiated only once, it's recommended to place it here.
The nice thing about this way of configuring services is the configuration method is contained and located within the service itself. There is no magic happening that is abstracted away by the framework.