每个组件都可以使用ComponentMetadata中的“providers”属性指定新的Providers。
有没有办法从组件的构造函数动态指定提供程序?
答案 0 :(得分:5)
我已经在bootstrap部分完成了它。
bootstrap(AppComponent,[
provide( RequestOptions, { useClass: DefaultRequestOptions } ),
provide(Http, { useFactory:
function(backend, defaultOptions) {
return new Http(backend, defaultOptions); },
deps: [XHRBackend, RequestOptions]}),
]);
我猜它也可以在一个组件中完成:
https://angular.io/docs/ts/latest/api/http/Http-class.html
通过将决策添加到工厂函数而不是仅返回相同的对象,使其成为动态。
答案 1 :(得分:2)
我使用了 useFactory 来确定将用于提供什么类。 我分享关注的人。
在组件ts
@Component({
selector: 'app-chart',
templateUrl: './chart.component.html',
styleUrls: ['./chart.component.scss'],
providers: [
{ provide: DateTimeAdapter, useClass: MomentDateTimeAdapter },
{ provide: OWL_DATE_TIME_FORMATS, useValue: CUSTOM_FORMATS },
{ provide: OwlDateTimeIntl, deps: [SettingService],
useFactory: (settingsService) => settingsService.getLanguage()
}
]
})
在服务中获取类实例
@Injectable()
export class SettingService {
public getLanguage(){
return this.translate.currentLang == "ko" ? new KoreanIntl() : new DefaultIntl;
}
}
答案 2 :(得分:1)
以下是实施动态提供程序需要遵循的3个更广泛的步骤。请注意我已经评论了很多部分代码,以便我们专注于主要答案。如果您想查看详细步骤,请参阅此Angular tutorial
第1步: - 创建提供商的集合
创建集合,您可以使用push方法动态添加DI对象。
var providerscoll:any = [];
providerscoll.push({ provide: "1", useClass: DialogLogger });
providerscoll.push({ provide: "2", useClass: ConsoleLogger });
第2步: - 在“NgModule”中提供提供者集合。
请参阅方括号语法。
@NgModule({
// code removed for clarity
providers: [providerscoll]
})
export class MainModuleLibrary { }
步骤3: - 在构造函数中获取Injector对象
使用DI在构造函数中获取注入器对象,然后可以使用“Get”方法和令牌查找。因此,如果你提供“1”,那么你会得到一些东西,如果你提供“2”,你会得到一些东西。
// code removed for clarity
import { Injector } from '@angular/core';
// code removed for clarity
export class CustomerComponent {
constructor(public injector: Injector){
this.logger = this.injector.get("2");
}
}
答案 3 :(得分:0)
有一种使用ViewContainerRef
创建组件的方法,允许通过injector
,所以我想这应该可行,但仅限于动态创建组件:
创建注入器:
static create(options: {providers: StaticProvider[], parent?: Injector, name?: string}): Injector;
// @param injector The injector to use as the parent for the new component.
abstract createComponent<C>(
componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,
projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>;
伪代码:
class FooComponent {
constructor(
private readonly injector: Injector,
private readonly viewContainer: ViewContainerRef){
const customInjector = this.injector.create({ providers: [FooService], parent: injector });
this.viewContainer.createComponent(componentFactory, 0, customInjector );
...
}
}
或者类似地使用Angular CDK中的Portal。