Situation
I've been trying to find a way where I can instantiate a service that will purely sit "in the background" and listen to events (and do stuff) - which I would like to be created when the app initializes, and be forgotten about.
Unfortunately, I would need to use dependency injection into a component, for the service to be instantiated - most paths I take lead to using the AppComponent's constructor.
I won't be directly interacting with the service though (calling methods/properties), and want to keep it out of other components/services which don't have anything directly to do with it.
The service
The service and the logic in it is pretty straightforward. My service is based on a Dynamic page titles in Angular 2 tutorial.
The service will listen to NavigationEnd events from the Router, grab the ActivatedRoute, and then use the route's data to set the page title.
Unlike the example in the tutorial, I've created my own service instead of putting the logic within the AppComponent; I want to keep my separation of concerns tip-top.
page-title.service.ts:
import { Injectable } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { filter, map, mergeMap } from 'rxjs/operators';
@Injectable()
export class PageTitleService {
constructor(
router: Router,
activatedRoute: ActivatedRoute,
titleService: Title
) {
router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => activatedRoute),
map((route) => {
while (route.firstChild) {
route = route.firstChild;
}
return route;
}),
filter((route) => route.outlet === 'primary'),
mergeMap((route) => route.data)
)
.subscribe((routeData) => titleService.setTitle(routeData['title']));
}
}
Obviously, the service itself will rely on dependency injection to use the Router, ActivatedRoute, and Title services.
The problem
The only way I currently know to instantiate this service is to use dependency injection into another component/service.
E.g. in app.component.ts:
export class AppComponent implements OnInit {
constructor(
pageTitleService: PageTitleService, // inject the service to instantiate it
// ... other services
) { }
ngOnInit() {
// do stuff with other services, but not the pageTitleService
}
}
The problem is, I want to avoid doing this if at all possible.
Question
Is it possible to instantiate the service somewhere other than a component/service?
Possibility?
I do have an app-load.module.ts, which does some upfront initialization, before the rest of the app is loaded:
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { OrganisationService } from './core/organisation/organisation.service';
export function initApp(organisationService: OrganisationService) {
return () =>
organisationService
.initialize()
.then(() => window.document.documentElement.classList.remove('app-loading'));
}
@NgModule({
imports: [],
declarations: [],
providers: [
OrganisationService,
{ provide: APP_INITIALIZER, useFactory: initApp, deps: [OrganisationService], multi: true }
]
})
export class AppLoadModule { }
Could I perhaps instantiate the PageTitleService in here, somewhere?
Or, is there a better place/way to do it?
Thanks in advance.