Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a service that requires constructor parameters?

I have a component that declares the MetricsService service. This service requires both HttpModule plus two strings that defines the host and the auth key to use.

The metrics service is as follows:

@Injectable() export class MetricsService {     constructor(         private http: Http,         public wsAuthKey: string,         public wsHost: string         ) {         this.wsAuthKey  = wsAuthKey || "blahblahblahblahblahblahblahblah=";         this.wsHost     = wsHost    || "https://preprod-admin.myservice.ws";     } 

The component that uses it is written as follows:

export class DatavizComponent implements OnInit, OnChanges {     constructor(         private zms: MetricsService,     ) {      } 

My question is how should I write the component constructor so that the whole thing works, including passing the host and key (but not passing the http)?

Note : The code as currently written does not compile.

To be more precise, I would expect the component to provided app-depending data something like this:

 export class DatavizComponent implements OnInit, OnChanges {         constructor(             private zms = MetricsService("http://myhost.com", "mykey"),         ) {          } 

But if this works, how to pass http?

UPDATE AFTER PROPOSED SOLUTION:

export class MetricsService {      constructor(         private http: Http,         @Inject('wsAuthKey') @Optional() public wsAuthKey?: string,         @Inject('wsHost') @Optional() public wsHost?: string         ) {         this.wsAuthKey  = wsAuthKey || "blahblah=";         this.wsHost     = wsHost    || "https://preprod-admin.host.ws";           console.log("MetricsService constructor="             + " wsAuthKey="+this.wsAuthKey             + ", wsHost="+this.wsHost         );      } 

In the component:

@Component({     selector:    'dataviz-offers-volumes',     templateUrl: 'app/dataviz.component.html',     styleUrls:  ['app/dataviz.component.css'],     encapsulation: ViewEncapsulation.None,     providers: [         {provide: 'wsAuthKey',  useValue: 'abc'},          {provide: 'wsHost',     useValue: 'efg'},      ], }) export class DatavizComponent implements OnInit, OnChanges {      @ViewChild('chart') private chartContainer: ElementRef;     @Input() private graphId:string;     @Input() private wsAuthKey:string;     @Input() private wsHost:string;     @Input() private maxSamples=12;      constructor(         private zms: MetricsService     ) {      } 

In the constructor, the log are as follows (value are not passed):

MetricsService constructor= wsAuthKey=blahblah=, wsHost=https://preprod-admin.host.ws 

where it should show 'abc' and 'efg'.

But I wonder if there is not an issue with the component that use dataviz componenet. In this component, the following information have been passed:

@Input() private wsAuthKey:string; @Input() private wsHost:string; 

As I would like the tag to optionally preset the host and key:

                <h1>dataviz volume</h1>                 <div class="chartContainer left" title="Simultaneous offers via dataviz directive">                     <dataviz-offers-volumes                          id="dataviz-volumes1"                         [graphId]="graphId"                         [wsAuthKey]="'myauthkey'"                         [wsHost]="'http://myhost.com'"                         [maxSamples]="123"                     >                     </dataviz-offers-volumes>                 </div> 
like image 411
Stéphane de Luca Avatar asked Feb 22 '17 16:02

Stéphane de Luca


People also ask

Can a service have a constructor Angular?

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

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 constructor have a parameter list?

Parameterized Constructor – A constructor is called Parameterized Constructor when it accepts a specific number of parameters. To initialize data members of a class with distinct values.

How many parameters should a constructor have?

This method has four parameters: the loan amount, the interest rate, the future value and the number of periods.


1 Answers

You can make the parameters optional by adding @Optional() (DI) and ? (TypeScript), and @Inject(somekey) for primitive values that are not supported as provider keys

@Injectable() export class MetricsService {     constructor(         private http: Http,         @Inject('wsAuthKey') @Optional() public wsAuthKey?: string,         @Inject('wsHost') @Optional() public wsHost?: string         ) {         this.wsAuthKey  = wsAuthKey || "blahblahblahblahblahblahblahblah=";         this.wsHost     = wsHost    || "https://preprod-admin.myservice.ws";     } 
providers: [   {provide: 'wsAuthKey', useValue: 'abc'},    {provide: 'wsHost', useValue: 'efg'},  ] 

If they are provided, they are passed, otherwise they are ignored, but DI still can inject the MetricsService.

like image 179
Günter Zöchbauer Avatar answered Sep 22 '22 17:09

Günter Zöchbauer