Skip to content

Feature Request: Add 'newInstanceOf' to "providers" #22756

Closed

Description

@asgerjensen

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Component providers does not have a way of getting a new instance of a module defined provider.
This makes component reuse difficult between projects, if a component needs a "private instance" of an otherwise global service.

Expected behavior

Ideally, I'd like to be able to get a new instance of whatever Service is defined to be in the injector tree.

I propose a newInstanceOf or newInstance keyword in the provide struct, that would walk up the tree and return a new instance of that class.

I.e.

@Component({
    providers: [
       { provide: Service, newInstance: true }
   ])

or incase I want to rename the service token

@Component({
    providers: [
       { provide: new InjectionToken<Service>('LocalService'), newInstanceOf: Service }
   ])

Minimal reproduction of the problem with instructions

  1. Create new project with ng new
  2. Create two services, let one extend the other.
     @Injectable()
     export class Service {};

      @Injectable()
       export class BetterService extends Service {};
  1. In app.module provide the extended service as the base service.
    { provide: Service, useClass: BetterService }
  2. in app.module add constructor with
  constructor(service: Service) {
    console.log('module', service.constructor.name);
  }
  1. In app.component, add to @Component
    providers: [ Service ]
  1. In `app.component add constructor
  constructor(service: Service) {
    console.log('component', service.constructor.name);
  }
  1. Run.

Observe that console shows
Module BetterService
Component Service

What is the motivation / use case for changing the behavior?

Writing components or entire modules that can take be reused between projects, while being able to have new versions of services injected, even when those are used as private instances. Notably, the Component, as its being reused, should not have knowledge of what concrete implementations of Service is available, just that it needs a private instance of whatever acts on behalf of Service right now.

Consider two services

 - Service
       - BetterService extends Service

In app.module.ts I can now define that 'Service' should provide 'BetterService'

   { provide: Service, useClass: BetterService }

In my component i need a new instance of whatever Service is defined to be, in the global scope, but as the component is a shared component, it should not know that BetterService exists.

@Component({
    providers: [
       { provide: Service, useClass: ??? }
   ])

Environment


Angular version: 5.2.3


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Activity

  1. added this to the needsTriage milestone on Mar 14, 2018
  2. trotyl commented on Mar 14, 2018

    @trotyl
    Contributor

    Duplicate of #18015

  3. asgerjensen commented on Mar 14, 2018

    @asgerjensen
    Author

    While I see how these are related, I dont think its a duplicate.

    #18015 is concerned with avoiding writing the "providers" section on a component level to get new instances, while this is concerned with being able to write a "providers" section on the component level, that would re-use the "definition" of the binding, from the module level. I.e. allow a component to say " I want to get an instance of whatever provides Service at this time", but without knowing exactly what subclass of Service is currently being applied to the application.

  4. added
    area: coreIssues related to the framework runtime
    on Mar 14, 2018
  5. trotyl commented on Mar 15, 2018

    @trotyl
    Contributor

    I agree, this one is more logical and sound.

  6. dawidgarus commented on Mar 16, 2018

    @dawidgarus

    Here's workaround to achieve desired behavior: https://plnkr.co/edit/olWXoB1X4BN4dTmFYF28?p=preview
    Main drawback is that You have to define static property parameters. It's not completely non-standard. Angular actually uses it instead of reflections to determine dependencies, so when You have parameters there's no need for @Injectable or other decorators.
    It would be much cleaner if there was some standard way to get list of dependencies or provider for injected value.
    Dunno if it works with AOT.

  7. added
    featureLabel used to distinguish feature request from other issues
    on Mar 29, 2018
  8. modified the milestones: needsTriage, Backlog on Mar 29, 2018
  9. angular-robot commented on Jun 4, 2021

    @angular-robot
    Contributor

    Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

    Find more details about Angular's feature request process in our documentation.

  10. angular-robot commented on Jun 24, 2021

    @angular-robot
    Contributor

    Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.

    We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.

    You can find more details about the feature request process in our documentation.

  11. angular-automatic-lock-bot commented on Apr 28, 2022

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  12. locked and limited conversation to collaborators on Apr 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimecore: difeatureLabel used to distinguish feature request from other issues

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions