Root services dependencies / SCAM

Viewed 26

With the completion of the RFC for standalone components, directives, and pipes: https://github.com/angular/angular/discussions/43784 we have started converting our application over.

We've hit a snag with services though. We have several services in our system that inject other services and potentially pipes. A common use case is DatePipe helping us transform data. We'd like our services to be singletons and so they have providedIn: 'root' so that any lazy loaded modules do not create a new one.

We've created the following service:

@Injectable({
  providedIn: 'root',
})
export class TestService {
  constructor(private truthyPipe: TruthyPipe) {
    console.log('I was constructed');
  }
  log() {
    console.log('test service');
  }
}

And the corresponding TruthPipe/Module:

@Pipe({
  name: 'truthy',
})
export class TruthyPipe implements PipeTransform {
  transform(value: any, args?: any): any {
    return !!value;
  }
}

@NgModule({
  declarations: [TruthyPipe],
  exports: [TruthyPipe],
  providers: [TruthyPipe],
})
export class TruthyPipeModule {}

And then the only thing we could try via following the SCAM principles was to create a TestService module and import the TruthyPipeModule:

@NgModule({
  imports: [TruthyPipeModule],
  declarations: [],
  exports: []
})
export class TestServiceModule {}

The TestServiceModule would then be imported into any component that needs to use the TestService. Our expectation was that this would work, but instead we get an error about TruthyPipe not being provided. The only way to fix this was to provide TruthyPipe in the root app.module. This doesn't seem (in our opinion) what we should be going for as it would bloat our main app module if the service is never used and yet the pipe would still be imported.

Here's a stackblitz demonstrating the problem: https://stackblitz.com/edit/angular-xkhwkw-8wpraz. Clicking on customers throws the error:

ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(CustomersModule)[TestService -> TestService -> TruthyPipe -> TruthyPipe -> TruthyPipe]: 
  NullInjectorError: No provider for TruthyPipe!
0 Answers
Related