vinnylinux
vinnylinux

Reputation: 7024

Dealing with service configuration in Angular 2 DIC

Coming from a Java background, it's being hard for me to understand a few things about Angular, specially the dependency injection mechanism. It's quite different from what i'm used to. Right now i'm trying to understand how it's possible to inject configuration variables into a service i'm creating:

@Injectable()
export class MyBackendService {
    constructor(url: string, version: string, token: string, secret: string) { }
}

All those strings are stored in my environment.{env}.ts files. But i have no idea how to tell Angular to fetch those variables and inject into my service class. Does anyone have any tip on the idiomatic way of doing this?

Upvotes: 1

Views: 1910

Answers (1)

Jaime Beneytez
Jaime Beneytez

Reputation: 171

In order to inject a dependency from the Angular DIC the dependency should be registered in it.

The way to register an Injectable entities in the DIC is through an @NgModule. and then import this one from the module which uses it.

In order to register a service or a value to the DIC it should be in the providers array of the NgModule.

In this concrete example ( if you need to add it to the DIC ) I would prefer to inject a config value to the BackendService with all the data required for that service taken from a config file of the app:

1 Configuration

  • Config Module

    import { NgModule } from '@angular/core';
    import { CONFIG } from "...";
    
    @NgModule({
        providers: [
            { provide: CONFIG, useValue: CONFIG }
        ]
    })
    export class ConfigModule{}
    
  • Config value

    export const CONFIG = {
    
         endpoint: {
            service1: {
                url: 'http://api.your-app.com/service1/',
                withCredentials: true,
                ...
            },
        }
    }
    

2 Service (consumer of the config)

  • Module:

    import { NgModule } from '@angular/core';
    import { Service1 } from "...";
    import { CONFIG } from "...";
    import { ConfigModule } from "...";
    
    @NgModule({
        imports: [
            ConfigModule // Import the config module to make the config available for the services in this module
        ]
        providers: [
            { 
                provide: Service1 // Register your service in the DIC the one that performs the requests to that server endpoint,
                useFactory: (config) => new Service1(config),
                deps:[ 
                    CONFIG 
                ]
            }
        ]
    })
    export class ApiModule{}
    
  • Service

    import { NgModule } from '@angular/core';
    
    export class Service1{
    
        private _endpointUrl:string;
    
        constructor(config) {
            this._endpointUrl = config.endpoint.service1.url;
        }
    }
    

3 Module of the app that consumes the Service 1

    import { NgModule } from '@angular/core';
    import { ApiModule } from "...";

    @NgModule({
        imports: [
            ApiModule
        ]
        ...
    })
    export class AppComponent{}

So then your injection chain would be

AppComponent <- Service1 <- CONFIG

All this assumes that we want the config to be an injectable

but

Do we really need the config to be injected ?

In general the config is just a JSON structure and it use to be a constant that the app consumes and in this case I would just import it where it is needed using typescript import and avoiding adding it to the DIC. eg:

  • Service

    import {CONFIG} from '...';
    
    export class Service1{
    
        private config;
    
        constructor() {
            this._config = CONFIG;
        }
    }
    

    Later on if it needs to be loaded from an endpoint that can be solved with the module loader ( SystemJS, Webpack ... ) you use in your app.

The down side of this shows up if you want to update the app configuration without reloading the browser and in that case in my opinion the config values should be provided by a configuration service provided by the DIC

Hope this helps.

Upvotes: 4

Related Questions