Configuring Angular Services

Posted on September 18, 2017

angular

This week I needed to turn an Angular module into an npm package that I could import into multiple projects. The tough part was that in this module, there was a service that posts to a URL which needed to be configured. Luckily, Angular provides a pretty simple way to do this, although it did take a little time to learn exactly how to do this. Hopefully by the end of this blog post you'll be able to do the same in your app.

The first thing that you should do is read about this on the Angular docs. It talks about configuring a service using the module's forRoot method. To get this working, there are 4 steps:

  • Make a config class to use for the service configuration
  • Provide the configuration in the module's forRoot method.
  • Use the config object in the service itself
  • Pass in the config object when importing the module

Make a Config Class

This part is pretty simple, but a necessary step. Make a class in its own file that you export and has a constructor and the correct number of attributes for your use case. It can be one single attribute, or multiple. Any number will work.

export class ServiceConfig {
	public myAttr: string;

	constructor(obj: any) {
		this.myAttr = obj.myAttr;
	}
}
		

You'll be using this class in the module file, as well as in the service, so be prepared to import it in those places.

Provide the Configuration in the Module

In the module file, my-module.ts for example, you will need a forRoot method which provides both the service as well as the configuration so that you can pass it in when importing the module. Your module will look like this:

...

export class MyModule {
	static forRoot(config: ServiceConfig): ModuleWithProviders {
		return {
			ngModule: MyModule,
			providers: [
				{ provide: ServiceConfig, useValue: config },
				MyService
			]
		};
	}
}
		

Use the Config Object in the Service

After providing the config in the module, we also have to use that config object in the service. This part needs to be added to your service, my-service.ts.

...

private myAttr: string;

constructor(@Optional() config: ServiceConfig) {
	this.myAttr = config.myAttr;
}
		

You don't necessarily need to have the @Optional() decorator on the parameter in the constructor, but that is a possibility if you need it. Inside the constructor, set your local variable to the value that was passed in.

Pass in the Config on Import

The last step is to pass in the config object when you import the module. Let's say you're importing MyModule into your AppModule. your imports array will include this (this is just one line, obviously):

imports: [
	...,
	MyModule.forRoot({ myAttr: 'Here is the value I want to pass in'}),
	...,
]
		

This will pass in the config object that we've defined, and then you can use that value in your service.

Conclusion

Overall, this turned out to be pretty simple, but it still took me a little bit of time to get everything working properly and figured out. Hopefully this helps you and cuts down the amount of time it takes you to get up and running.