gt6707a
gt6707a

Reputation: 689

Inject a service requiring constructor parameter

I have a service that requires some value to be initiated:

@Injectable()
export class MyService {
  private myVals: any;

  constructor(init : any) {
    this.myVals = init;
  }
}

And the consumer:

@Component(...)
export class MyComponent {
  private svc: MyService;
  constructor(private svc : MyService) {
  }
}

So is there a way to inject and pass the required parameter to MyService's constructor "during" dependency injection??

Something like:

constructor(private svc({ // init vales }) : MyService) {}

I know I can pass by variable, but interested to find if there's a way to do this from the API.

Upvotes: 46

Views: 37209

Answers (3)

You can use @Inject, explained here

In your service:

import {Inject, Injectable} from '@angular/core';
    
@Injectable({
  providedIn: 'root'
})

export class NgService {
    constructor (
       @Inject('paramId') private paramId: string
    ) { }
}

And then, in your component:

import { Component } from '@angular/core';

@Component({
  selector: 'app-demo',
  template: `
    <div"> </div>
  `,
   providers: [
    {provide: 'paramId', useValue: 'param-id'},
  ]
})

export class AppComponent {

  constructor(private ngService: NgService) { }

}

Upvotes: 5

Black Mamba
Black Mamba

Reputation: 15545

The above answer has been deprecated since angular 4 Now you can use it like this:

import { NgModule, APP_INITIALIZER } from '@angular/core';

@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: onAppInit1,
      multi: true,
      deps: [/* your dependencies */]
    },
    {
      provide: APP_INITIALIZER,
      useFactory: onAppInit2,
      multi: true,
      deps: [/* your dependencies */]
    }
  ]
})
export class AppModule { }

Upvotes: 5

Ilya Chernomordik
Ilya Chernomordik

Reputation: 30195

There is an official way that Angular team recommends in here. It basically allows you to inject statically typed configuration classes.

I have successfully implemented it and here is all the relevant code:

1) app.config.ts

import { OpaqueToken } from "@angular/core";

export let APP_CONFIG = new OpaqueToken("app.config");

export interface IAppConfig {
    apiEndpoint: string;
}

export const AppConfig: IAppConfig = {    
    apiEndpoint: "http://localhost:15422/api/"    
};

2) app.module.ts

import { APP_CONFIG, AppConfig } from './app.config';

@NgModule({
    providers: [
        { provide: APP_CONFIG, useValue: AppConfig }
    ]
})

3) your.service.ts

import { APP_CONFIG, IAppConfig } from './app.config';

@Injectable()
export class YourService {

    constructor(@Inject(APP_CONFIG) private config: IAppConfig) {
             // You can use config.apiEndpoint now
    }   
}

Now you can inject the config everywhere without using the string names and with the use of your interface for static checks.

You can of course separate the Interface and the constant further to be able to supply different values in production and development e.g.

Upvotes: 27

Related Questions