Provide different Angular service based on condition at runtime

Let’s say you want to conditionally provide an implemenation for a service at runtime (if your app is in environment A, use the GoogleAuthService, and for environment B use the FacebookAuthService).

This can be achieved by registering a factory for the required provider and deciding at runtime what should be returned for an implemenation.

First, create the following base class service.

export abstract class AuthenticationService {
    abstract login(username:string, password:string);
    abstract logout();
}

Then, write the Google counterpart.

@Injectable()
export class GoogleAuthService extends AuthenticationService {
login(username:string, password:string){
//TODO login for Google
   }
   logout(){
//TODO logout
    }
}

And the Facebook counterpart.

@Injectable()
export class FacebookAuthService extends AuthenticationService {
login(username:string, password:string){
//TODO login for Facebook
   }
   logout(){
//TODO logout
   }
}

In your app.module.ts, you’ll register the factory that will create either of the service implementation (based on a condition, a flag in the configuration service in this case).

providers: [
{
    provide: AuthenticationService,
    useFactory: AuthenticationFactory,
    deps: [ConfigurationService]
   }
]

The authentication factory will switch based on a setting from the configuration to provide the correct authentication service.

export function AuthenticationFactory(configService: ConfigurationService) {
    if (configService.authprovider === 'google') {
       return new GoogleAuthService(configService);
    }
    return new FacebookAuthService(oauthService, configService);
}