3

I'm having problem injecting a service through standalone component's constructor.

Service is defined as Injectable with provider set to root:

@Injectable({ providedIn: 'root' }) export class ProductsService {...}

And in main.ts, for bootstrapApplication function call there's ProductsService defined in "providers" section.

This should be enough to be able to inject ProductsService singleton in component's constructor, yet it's not being recognized there (reported error: Cannot find name ProductsService).

I really do not want to use direct references to service inside of standalone component, nor inject function inside of component.

What am I missing here?

2
  • Remove from "providers" sections, but don't forget import {ProductService} from './your-path/your-service-component-file' (without .ts) Commented Dec 19, 2023 at 16:28
  • Thanks for reply, but how would I in that case maintain replaceability of service reference in constructor from the outside, for testing purposes for e.g.? Commented Dec 19, 2023 at 20:40

2 Answers 2

1

I imagine you can make a work-around: create a singleton service in the way

export interface ServiceInterface{
   ..definition of your interface..
}

export class SingletonService{
  private static instance: ServiceInterface;
  public static getInstance(): ServiceInterface{
    if (!SingletonService.instance) {
      getInstance.instance = new FoolService() as ServiceInterface;
    }

    return SingletonService.instance;
  }
}

To "import" the service in a component you use some like:

foolService!:ServiceInterface
constructor() {
  this.foolService=SingletonService.getInstance()
}

Now, if you want to change the function getService in SingletonService

  public static getInstance(): ServiceInterface{
    if (!SingletonService.instance) {
      //return "AnotherService"
      getInstance.instance = new AnotherService() as ServiceInterface;
    }

    return SingletonService.instance;
  }
Sign up to request clarification or add additional context in comments.

Comments

1

And in main.ts, for bootstrapApplication function call there's ProductsService defined in "providers" section.

No, it should not be there.

The purpose of @Injectable({ providedIn: 'root' }) is to do exactly that. You don't need to declare it in your application bootstrap too.

(reported error: Cannot find name ProductsService)

This one simply means you have not imported the file, so simply import it.

I really do not want to use direct references to service inside of standalone component, nor inject function inside of component.

You have to, that's how it works. If you do not specify what you want to inject, it is impossible for Angular to know what to inject.

2 Comments

Thank you for reply, what I'm worried about is that by referencing this service with import statement inside component (rather than setting it at bootstrap root level) I'm loosing important benefit of dependency injection - ability to easily replace service reference with another one at single location (for e.g. with mockup for testing purposes). Am I having wrong impression about this?
Kind of yes : first of, you can't do what you want. Secondly, you have what is called provider overriding, which will do what you want. You also have specific configurations you can do regarding file replacements, which can replace your files at runtime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.