Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow injection tokens to be provided in the same way as services #49807

Open
markostanimirovic opened this issue Apr 12, 2023 · 1 comment
Open
Labels
area: core Issues related to the framework runtime core: di feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Milestone

Comments

@markostanimirovic
Copy link
Contributor

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

Unlike services, injection tokens cannot be provided at the component/route level without using useFactory/Value/Class.

const BAR_TOKEN = new InjectionToken('Bar', {
  factory() {
    const foo = inject(FooService);
    return foo.bar;
  }
});

The BAR_TOKEN will be provided at the root level even if we don't use providedIn: 'root'. If we want to provide BAR_TOKEN at the component level, it cannot be provided in the following way:

@Component({
  providers: [BAR_TOKEN], // this will not work even if we defined `factory` for the `BAR_TOKEN`
})
export class BarComponent {}

To make it work, we need to explicitly specify its factory, although we have already defined factory in the BAR_TOKEN definition:

@Component({
  providers: [{ provide: BAR_TOKEN, useFactory: () => inject(FooService).bar }],
})
export class BarComponent {}

Proposed solution

Unlike tokens, with services, we need to add @Injectable({ providedIn: 'root' }) to provide them at the root level. I'd like to have the same behavior with injection tokens:

const BAR_TOKEN_1 = new InjectionToken('Bar', {
  providedIn: 'root',
  factory() {
    const foo = inject(FooService);
    return foo.bar;
  }
}); // BAR_TOKEN_1 is provided at the root level (no changes in this case)

const BAR_TOKEN_2 = new InjectionToken('Bar', {
  factory() {
    const foo = inject(FooService);
    return foo.bar;
  }
});

// BAR_TOKEN_2 is not provided anywhere by default,
// similar to `@Injectable()` that doesn't contain `{ providedIn: root }` config.
// However, `InjectionToken` with a factory can be provided in the following way:

@Component({
  providers: [BAR_TOKEN_2]
})
export class BarComponent {}

Alternatives considered

We can use inject... functions instead of injection tokens:

export function injectBar() {
  const foo = inject(FooService);
  return foo.bar;
}

However, by using this approach, the inject... function body will be executed every time when it's invoked. On the other hand, if we are able to use injection tokens in the way that is described in the previous section, the injection token factory will be executed only the first time when it's injected.

@markostanimirovic markostanimirovic changed the title Allow injection tokens to be provided in the same way as injectables Allow injection tokens to be provided in the same way as services Apr 12, 2023
@AndrewKushnir AndrewKushnir added feature Issue that requests a new feature area: core Issues related to the framework runtime core: di labels Apr 12, 2023
@ngbot ngbot bot modified the milestone: Backlog Apr 12, 2023
@angular-robot angular-robot bot added the feature: votes required Feature request which is currently still in the voting phase label Apr 13, 2023
@angular-robot
Copy link
Contributor

angular-robot bot commented Apr 13, 2023

This feature request is now candidate for our backlog! In the next phase, the community has 60 days to upvote. If the request receives more than 20 upvotes, we'll move it to our consideration list.

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

@angular-robot angular-robot bot added feature: under consideration Feature request for which voting has completed and the request is now under consideration and removed feature: votes required Feature request which is currently still in the voting phase labels Apr 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: core Issues related to the framework runtime core: di feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests

2 participants