Repository navigation
Description
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
- Create new project with
ng new - Create two services, let one extend the other.
@Injectable()
export class Service {};
@Injectable()
export class BetterService extends Service {};
- In
app.moduleprovide the extended service as the base service.
{ provide: Service, useClass: BetterService } - in
app.moduleadd constructor with
constructor(service: Service) {
console.log('module', service.constructor.name);
}
- In
app.component, add to@Component
providers: [ Service ]
- In `app.component add constructor
constructor(service: Service) {
console.log('component', service.constructor.name);
}
- 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
trotyl commentedon Mar 14, 2018
Duplicate of #18015asgerjensen commentedon Mar 14, 2018
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
Serviceat this time", but without knowing exactly what subclass ofServiceis currently being applied to the application.trotyl commentedon Mar 15, 2018
I agree, this one is more logical and sound.
dawidgarus commentedon Mar 16, 2018
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 haveparametersthere's no need for@Injectableor 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.
angular-robot commentedon Jun 4, 2021
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.
angular-robot commentedon Jun 24, 2021
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.
angular-automatic-lock-bot commentedon Apr 28, 2022
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.