Allan Barcelos
Allan Barcelos

Reputation: 25

Angular Dependency Providers

I have a service with parameter PATH and I to need set this parameter when I set this service in providers of module.

When I inject this service in some component of this module and I call any of the methods of that service, the parameter PATH will already be set.

I followed this doc https://angular.io/guide/dependency-injection-providers but it didn't help me.


@Injectable()
export class MyService {

  PATH: string;

  constructor(
    private otherService: OtherService,
  ) {
  }

  getAll() {
   return this.httpClient.post<InquiryResponse<any>>(this.PATH, request);
   // FYI: this is only for example purposes
  }

@NgModule({
  declarations: [
    SomeComponent,
  ],
  imports: [
    CommonModule,
  ],
  providers: [
    MyService  // < --- I need to set the parameter PATH here
  ]
})
export class MyModule {

export class MyComponent implements OnInit {


  constructor(
    private myService: MyService
  ) { }

  ngOnInit() {
    this.myService.getAll();  // <-- when call getAll the PATH already be set before in module
  }

Upvotes: 1

Views: 669

Answers (3)

Poul Kruijt
Poul Kruijt

Reputation: 71961

There are four options. Probably more, but I guess these are the most used once, and depending on your use case, you can decide what you need.

1. Using an INJECTION_TOKEN

With such a token you can inject a constant into your services using the providers array of your AppModule:

First create an injection token file:

path.token.ts

export const PATH = new InjectionToken<string>('PathToSomethingDescription');

app.module.ts

@NgModule({
  // ...
  providers: [
    { provide: PATH, useValue: 'https://foo-bar' } 
  ]
})
export class AppModule {}

my.service.ts

export class MyService {
  constructor(@Inject(PATH) path: string) {}
}

You can then use this.path from inside your service, and it will have the value provided in the providers definition. You can also override this InjectionToken if you want it to be different in certain modules


2. Using the environment file from angular cli

You can use the environment file to insert constants:

environment.ts

export const environment = {
  // ...
  path: 'https://foo-bar'
};

my.service.ts

export class MyService {
  PATH: string = environment.path;
}

3. Creating a tree-shakable provider

my-service.ts

@Injectable({
  providedIn: 'root',
  useFactory: () => new MyService('https://foo-bar'),
})
export class MyService {
  constructor(readonly PATH: string) {}
}

4. Creating a provider using useFactory across modules

If you need different values across modules, you should not do it like this, but add the useFactory from the @Injectable in your feature module:

random-feature.module.ts

@NgModule({
  providers: [
    // ...
    { provide: MyService, useFactory: () => new MyService('https://foo-bar') }
  ]
})
export class RandomFeatureModule {}

my-service.ts

export class MyService {
  constructor(readonly PATH?: string) {}
}

And then normally inject it wherever you need it. Be aware though that you will get different instances of the same service. This might lead to unexpected behaviour

Upvotes: 2

Xesenix
Xesenix

Reputation: 2558

There are at least few ways of doing it maybe simpliest for using some path param would be create InjectionToken for it like this:

// in service you add token definition:
export const PATH = new InjectionToken<string>('PATH');

@Injectable()
export class MyService {
  constructor(
    @Inject(PATH) private path: string,
  ) {
  }
  ...
}
// in module import token and add value for it
import { PATH, MyService } from './service';

@NgModule({
  ...
  providers: [
    MyService,
    {
      provide: PATH,
      useValue: 'some/path/value'
    },
  ]
})
export class MyModule {

Read more about InjectionToken

Upvotes: 0

Antoniossss
Antoniossss

Reputation: 32550

What you want is factory provider. It allows you to parametrize service creation https://angular.io/guide/dependency-injection-providers#factory-providers

Upvotes: 1

Related Questions