Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: Import service based on environment

Tags:

angular

What is the best/proper way to import a service based on the current environment within an angular-cli project?

I have setup up a new environment called dev-mock which I can call with ...

ng serve --environment=mock

I then set up the provider in the module with useClass

app/app.module.ts ...

import {environment} from '../environments/environment';
import {ApiService} from './api/api.service';
import {MockApiService} from './api/mock/mock-api.service';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [
    {
      provide: ApiService,
      useClass: (environment.name === 'dev-mock') ? MockApiService : ApiService
    }
  ],
  bootstrap: [AppComponent]
})

This works fine, the problem then is what do I do when I want to inject that into another service or component, for example ...

app/ticket/ticket.service.ts

import {ApiService} from '../api/api.service'; // *** WHAT AM I TO DO HERE? ***

@Injectable()
export class TicketService {

  constructor(private api: ApiService, private http: Http) {
  }

}

Obviously my approach is wrong. What is the correct approach?

like image 654
pashioz Avatar asked Oct 17 '22 14:10

pashioz


1 Answers

Create interface for MockApiService and ApiService eg. IApiService. If you want to interchange them there has to be one.

Create a file with token and export it:

import { OpaqueToken } from '@angular/core';
export let API_SERVICE = new OpaqueToken('api.service');

Then register your service somewhere using the token:

const apiServiceClass = (environment.name === 'dev-mock') ? MockApiService : ApiService;

providers: [{ provide: API_SERVICE, useClass: apiServiceClass }]

Finally you can use it in any place using Inject() decorator applied in constructor, eg.

import {IApiService} from '../api/iapi.service';
import { Inject, Injectable } from '@angular/core';

@Injectable()
export class TicketService {

  constructor(@Inject(API_SERVICE) private api: IApiService) {}
}

The trick is to gice interface as type of property and use Inject() with OpaqueToken to tell dependency injector what it should put.

like image 199
kit Avatar answered Nov 15 '22 05:11

kit