How to inject a service into a class that must be instantiated in app module in angular 7?

973 views Asked by At

I am using ngxs in a project and I want to use the ngxs logger plugin, but I want to override the logger itself so that I am able to log to the backend. For this I need to inject my RestService in my logger class but I am not being able to do so. I have seen multiple questions where it is asked how to inject services into plain classes but those cases don't really answer the case where you have to manually instantiate the class at the app module. This, this and this are such answers that failed to help me or I failed to grasp their knowledge.

Here is what I have in my app module's imports:

export const APP_MODULE_IMPORTS = [
  NgxsModule.forRoot([
    NewsState,
    NewsAdminState,
  ]),
  NgxsReduxDevtoolsPluginModule.forRoot(),
  NgxsLoggerPluginModule.forRoot({
    collapsed: false,
    logger: new Logger(/* Need somehow to have an instance of the RestService HERE without having to pass all other dependencies */)
  }),
  BrowserModule,
  HttpClientModule,
  FormsModule,
  ReactiveFormsModule,
  routing
];

And here's my logger class:

import { RestService } from 'my-angular-modules';

@Injectable()
export class Logger {

  constructor(private restService: RestService) {
  }

  public log(title, color, payload): void {
    console.log(title, 'title');
    console.log(color, 'color');
    console.log(payload, 'payload');
  }

  public groupCollapsed(message): void {
    console.groupCollapsed(message);
  }

  public group(message): void {
    console.group(message);
  }

  public groupEnd(): void {
    console.groupEnd();
  }
}

I cannot pass an instance of rest service directly because I would have to pass a cascade of dependencies. I also tried using injection tokens and add { provide: LOGGER_INJECTION_TOKEN, useClass: RestService } to providers but I got to the same point. I don't know how to instantiate the Logger class at that point without having to pass these arguments that I don't have.

Is this even possible? If not, how should I do this? I want to be able to use the ngxs logger to store the logs of the actions instead of creating custom logging in the components but for that I need the logger to be able to use my rest service.

1

There are 1 answers

4
eranshmil On BEST ANSWER

You could try using a provider factory:

export function createLoggerPluginOptions(httpClient: HttpClient) {
  return {
    logger: new Logger(httpClient)
  }
}


// and provide in the module:
{
  provide: NGXS_LOGGER_PLUGIN_OPTIONS,
  useFactory: (createLoggerPluginOptions),
  deps: [HttpClient]
}

Here is a working example: https://stackblitz.com/edit/ngxs-custom-logger