Angular 5 Injector - How to inject string
Solution 1
get is deprecated: from v4.0.0 use Type or InjectionToken
warning refers to the fact that injector.get
is generic method and expects type argument. This is exactly what Injector
documentation states:
get(token: Type | InjectionToken, notFoundValue?: T): T
Considering that name
string token is supposed to resolve to a string, it should be:
this.injector.get<string>(<any>'name');
String tokens are deprecated as well, and a token is expected to be either a function or InjectionToken
instance.
however I don't want to useValue or useClass, what I need is the actual value injected.
All dependencies should be registered as module or component providers in order to be injected.
Solution 2
First you need to create an InjectionToken
(here in values.ts
):
import { InjectionToken } from '@angular/core';
export const PAGE_TITLE = new InjectionToken<string>('page.title');
Then you need to import it into your module and provide a value when that token is requested:
providers: [ HeroService, MessageService,
{ provide: PAGE_TITLE, useValue: "My Wonderful Title" }
],
Then you need to import that token where you want to inject the value and use @Inject()
:
constructor(@Inject(PAGE_TITLE) title) {
this.title = title;
}
Looking at ReflectiveInjector
it says it is slow and to use Injector.create
instead btw...
Royalsmed
Updated on June 11, 2022Comments
-
Royalsmed almost 2 years
I am trying to inject strings into my angular component. The code below works fine but it gives a deprecation warning: get is deprecated: from v4.0.0 use Type or InjectionToken
@Component({ selector: 'app-label', templateUrl: './label.component.html', styleUrls: ['./label.component.scss'] }) export class LabelComponent { public name: string; public caption: string; constructor( private injector: Injector ) { this.name = this.injector.get('name'); this.caption = this.injector.get('caption'); } }
So i tried to work with this very short and incomplete documentation Angular 5 Injector to come up with something like below, however I don't want to
useValue
oruseClass
, what I need is the actual value injected.class BS { } // [..] const name = new InjectionToken<string>('name'); const caption = new InjectionToken<string>('caption'); const injector = ReflectiveInjector.resolveAndCreate([ { provide: name, useClass: BS}, { provide: caption, useClass: BS} ]); this.name = this.injector.get(name); this.caption = this.injector.get(caption); console.log(this.name); // will be an instance of BS
I am really stuck here and the documentation is not helping at all.
I need this for Dynamic component Loading and Injection. Full Plunker can be found in: Plunker Dynamic Component Loading and Injection
-
Royalsmed about 6 yearsThat's not what I am looking for actually, I could achieve the same with the code above and
useValue
{ provide: name, useValue: 'bs1'}, { provide: caption, useValue: 'bs2'}
The injected values are dynamic and coming from another service. -
Jason Goemaat about 6 yearsI'm don't understand, if the values are being provided by a service, shouldn't the service be injected? Are you trying to create a service that ties into the injection at run-time and dynamically alters the values that will be injected when new instances are created?
-
Estus Flask about 6 years@Royalsmed Then the question is XY problem. Generally you don't need to use ReflectiveInjector at all for regular tasks. If you need it, you can be sure that you're doing something wrong.
-
Royalsmed about 6 yearsunfortunately this is not how it works.
this.injector.get<string>('name');
won't work becauseArgument of type '"name"' is not assignable to parameter of type 'InjectionToken<string> | Type<string>'.
-
Royalsmed about 6 years@estus I don't think I am doing something wrong but I might be wrong :p here is a full Plunker with what I am trying to achieve link
-
Estus Flask about 6 yearsI updated the answer with explanation. String tokens are deprecated, and you have to cheat it with
<any>
. In your case embed.plnkr.co/p7VHB4 I see no reason why string tokens should be used. You can use InjectionToken there. -
Royalsmed about 6 yearsCan you please explain a bit more
I see no reason why string tokens should be used. You can use InjectionToken there
-
Estus Flask about 6 yearsBecause string tokens provide global-like behaviour. You can use token in another module without importing it. They have some drawbacks as globals - loose coupling, namespace pollution and collisions. String tokens were considered antipatterns for these reasons and so were deprecated.
-
Royalsmed about 6 yearsok that is clear, but what do you suggest to use?
this.injector.get<string>(<any>'name');
is this the right way or an even better option to create a class and inject it instead of single properties? -
Estus Flask about 6 yearsIt depends on the case. In your case there doesn't seem to be reasons why there should be many providers. You could create a single
componentConfig
InjectionToken provider withname
andpayload
props. As for ReflectiveInjector, it is usually not necessary, and I guess here too - usually you can pass data to dynamically created component throughinputs
.