Search code examples
angularangular-dependency-injection

How to provide an implementation for a given class using DI in Angular?


Consider that I have 2 modules called A and B.

Let's say I have this class. It doesn't really "belong" to any module since it's a plain old Typescript class rather than an Injectable.

class Greeter {
  constructor(private greeting: string) {}

  greet(name: string) {
    console.log(`${greeting}, ${name}!`);
  }
}

Cool. Then, let's say module A exports a component that injects a Greeter instance.

@Component({ ... })
class GreetingComponent {
  name: string;

  constructor(private greeter: Greeter) {}

  greet() { this.greeter.greet() }
}

Nice. Now let's say module B has a service that extends the Greeter class. Module B imports module A.

@Injectable({
  providedIn: 'root'
})
class GentleGreeterService extends Greeter {
  constructor() {
    super('Hello');
  }

  greet(name: string) {
    super.greet(name);
    console.log('How are you doing?');
  }
}

Cool. Now, whenever I use GreetingComponent in module B, I expect a GentleGreeterService instance to be injected. However, I get no instance at all, but rather NullInjectorError: No provider for Greeter. How can I fix this?


Solution

  • You should read about providers in the official docs - I'm sure they'll explain it better than me.

    Long story short - you only have a provider for GentleGreeterService but not for Greeter. You can add a provider (i.e. on module level, but also on component level) that will provide a Greeter but using some other class (or resolve it in other way, e.g. using a factory):

    providers: [{provide: Greeter, useClass: GentleGreeterService}]