英文:
How to specify injections into component at creation?
问题
I've translated the code portion for you:
也许我误解了依赖注入的目的,但我创建了一个使用Service
来获取一些数据的组件:
export abstract class MyService {
abstract getData(): string;
}
@Injectable({
providedIn: 'root'
})
export class FooService extends MyService {
getData() { return "foo"; }
}
@Injectable({
providedIn: 'root'
})
export class BarService extends MyService {
getData() { return "bar"; }
}
@Component({
selector: 'my-component',
template: '<span> {{ data }} </span>'
})
export class MyComponent implements Component {
data: string;
constructor(service: MyService) {
this.data = service.getData();
}
}
如何在创建MyComponent
时注入适当的Service
,无论是FooService
、BarService
还是MyService
的其他子类?
我期望存在类似<my-component [service]="FooService"></my-component>
的方式,但是在文档中找不到类似的内容。
英文:
Perhaps I've misunderstood the purpose of dependency injection, but I went and created a component that uses a Service
to get some data:
export abstract class MyService {
abstract getData(): string;
}
@Injectable({
providedIn: 'root'
})
export class FooService extends MyService {
getData() { return "foo"; }
}
@Injectable({
providedIn: 'root'
})
export class BarService extends MyService {
getData() { return "bar"; }
}
@Component({
selector: 'my-component',
template: `<span> {{ data }} </span>`
})
export class MyComponent implements Component {
data: string;
constructor(service: MyService) {
this.data = service.getData();
}
}
How do I get the appropriate Service
, whether FooService
or BarService
or some other subclass of MyService
injected into a MyComponent
when I create it?
I was expecting that there would exist something like <my-component [service]="FooService"></my-component>
, but I can't find anything like this in the docs.
答案1
得分: 1
From parent component providers array we can set different instance to same MyService using useExisting
or useFactory
.
When we provide a service in a component's providers array, the instance of that service is scoped to that component and its children.
@Component({
providers: [
{
provide: MyService,
useExisting: BarService // FooService
}
],
})
或者
如果您使用的是 Angular 14+,您可以将 inject
函数与环境注入器结合使用以获得类似的行为。
@Input() service: ProviderToken<MyService>;
constructor(private envInj: EnvironmentInjector) {
}
ngOnInit() {
this.envInj.runInContext(() => {
if (this.service) {
this.data = inject(this.service).getData();
}
})
}
英文:
From parent component providers array we can set different instance to same MyService using useExisting
or useFactory
When we provide a service in a component's providers array, the instance of that service is scoped to that component and its children
@Component({
providers:[
{
provide:MyService,
useExisting:BarService //FooService
}
],
})
Or
If you are using angular 14+ you could combine inject function with Environment injector to get similar behaviour
@Input() service:ProviderToken<MyService>;
constructor(private envInj:EnvironmentInjector) {
}
ngOnInit() {
this.envInj.runInContext(()=>{
if(this.service){
this.data = inject(this.service).getData();
}
})
}
答案2
得分: 0
Jay Swaminarayan!
我猜你应该这样做,这是更简单的方式!
export abstract class MyService {
abstract getData(): string;
}
@Injectable({
providedIn: 'root'
})
export class FooService extends MyService {
getData() { return "foo"; }
}
@Injectable({
providedIn: 'root'
})
export class BarService extends MyService {
getData() { return "bar"; }
}
@Injectable({
providedIn: 'root'
})
export class AllServices {
constructor(public Foo: FooService,public Bar: BarService) {}
}
@Component({
selector: 'my-component',
template: '<span> {{ data }} </span>'
})
export class MyComponent implements Component {
@Input() service: MyService;
data: string;
constructor(public _: AllServices) {
this.data = this.service.getData();
}
}
然后在模板中按照你的需求使用它:
<my-component [service]="_.Foo"></my-component>
<my-component [service]="_.Bar"></my-component>
这可能不是标准的方式,但也能达到相同的目的并匹配你的实现。
英文:
Jay Swaminarayan!
I guess you should do this instead, it's more simple way!
export abstract class MyService {
abstract getData(): string;
}
@Injectable({
providedIn: 'root'
})
export class FooService extends MyService {
getData() { return "foo"; }
}
@Injectable({
providedIn: 'root'
})
export class BarService extends MyService {
getData() { return "bar"; }
}
@Injectable({
providedIn: 'root'
})
export class AllServices {
constructor(public Foo: FooService,public Bar: BarService) {}
}
@Component({
selector: 'my-component',
template: `<span> {{ data }} </span>`
})
export class MyComponent implements Component {
@Input() service: MyService;
data: string;
constructor(public _: AllServices) {
this.data = this.service.getData();
}
}
Then use it in your template as you desired.
<my-component [service]="_.Foo"></my-component>
<my-component [service]="_.Bar"></my-component>
This may not be standard way, but kind of serves the purpose as well as match your implementation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论