18

每个组件都可以Provider使用其providersin 中的属性指定 new ComponentMetadata

有没有办法从constructor组件中动态指定提供者?

4

4 回答 4

14

我使用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()
        }
    ]
})

在服务中 ts 获取类实例

@Injectable()
export class SettingService {
    public getLanguage(){
       return this.translate.currentLang == "ko" ? new KoreanIntl() : new DefaultIntl;
    }
}
于 2019-09-05T08:21:28.873 回答
7

以下是实施动态提供程序需要遵循的 3 个更广泛的步骤。请注意,我已经评论了代码的许多部分,以便我们专注于主要答案。如果您想查看详细步骤,请参阅此Angular 教程

第 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");
    }
}
于 2017-11-15T07:48:06.513 回答
6

我已经在引导部分完成了。

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

您可以通过将决策添加到工厂函数中来使其动态化,而不仅仅是返回相同的对象。

于 2016-01-11T00:01:59.370 回答
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 。

于 2020-06-12T09:33:40.850 回答