Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass parameter to service constructor

Tags:

angular

Let's suppose I have this Angular 2 service:

@Injectable()
class Demo {
    constructor(private instanceSpecificString: string) {
    }
}

Notice that its constructor accepts an instance-specific string. What I mean by that is that I want to instantiate this service multiple times and, each time it gets instantiated, I want to pass it a different string based on the context in which the service is instantiated.

How do I do that?

P.S. string is used as an example, but the parameter could easily be of type number, or boolean or even some kind of configuration object.

like image 815
battmanz Avatar asked May 23 '16 23:05

battmanz


People also ask

How do I pass a parameter to a service in Angular 6?

If you want to pass additional parameters to an Angular service, what you are looking for is @Inject decorator. It helps you pass your parameters to the service through Angular's dependency injection mechanism. @Inject() is a manual mechanism for letting Angular know that a parameter must be injected.

Can a service have a constructor Angular?

Also, DI in our Angular components/services can be implemented using either constructor or injector.

How do you dynamically inject a service?

Acquiring a service dynamically through injector in Angular 2(+) is pretty straightforward. All you have to do is inject the Injector itself into the component's constructor instead of the services and then get the service instance by using the injector. get() method.


2 Answers

The value that gets passed to your service will be determined by the injector that's instantiating it. You might be able to do this in one of your component definitions:

@Component({
    ...
    providers: [
        provide(string, {useValue: "someSpecificValue"})
    ]
})

However, this has the problem that you're defining a provider for the string token and that could lead to maintainability issues.

It would probably be a better pattern to define some config model for your service:

class DemoConfig {
    instanceSpecificString: string;
}

And then you could create an instance of that to pass to your service.

let config = { instanceSpecificString: "someSpecificValue" }

@Component({
    ...
    providers: [
        provide(DemoConfig, {useExisting: config})
    ]
})

Hope this is helpful. I haven't tried this myself; the services I use in my application are singletons. Here is the reference that I was using:

https://angular.io/docs/ts/latest/api/core/index/provide-function.html

like image 57
awiseman Avatar answered Sep 30 '22 06:09

awiseman


Because the service is declared a injectable (@Injectable() annotation) it is a singleton. So instead just remove the annotation from the top of your service to remove that restriction.

This is not necessarily best practices but it will work and compile with AOT enabled.

Example:

Change this service:

@Injectable()
export class BaseSocket extends Socket {   
  protected constructor(
    private baseConfig:SocketIoConfig
    ...   
  ) {
    super();   
  } 
}

Into this:

export class BaseSocket extends Socket {
  protected constructor(
    private baseConfig:SocketIoConfig
    ...
  ) {
     super();
  }
}
like image 39
Jeremy Avatar answered Sep 30 '22 05:09

Jeremy