首页 文章

Angular 4:如何将参数传递给模块文件中提供的服务

提问于
浏览
7

我正在打电话给你,要求你在这里使用什么方法:我已经测试了许多东西来解决我的问题,我至少有4个工作解决方案,但我不知道哪一个是最好的,如果其中一些只是因为我所做的其他事情的副作用而工作,不应该使用...

我在文档中找不到任何指向这些解决方案(或另一个)的解决方案

First, here's my situation :我正在构建一个连接到数据API的应用程序,并构建不同的部分,每个部分都包含dataviz .

我将站点的各个部分构建为模块,但它们共享一个名为DataService的服务(这些模块中的每一个都将使用DataService来获取和处理数据) .

我的DataService需要一个配置文件,其中包含许多特定于每个部分的选项,并存储在它自己的文件夹中 .

因此,我需要在module.ts文件的providers部分中为每个部分单独提供DataService,并且避免将DataService复制到每个模块似乎是一种好习惯...

所以文件的架构是:

--Dashboard module
----data.service.ts
----Section1 module
------Section1 config file
----Section2 module
------Section2 config file

我尝试了多个似乎在部分模块文件中工作的东西:

Solution 1 : injection

(即使我没有在任何地方看到这种情况,我也无法在没有引号的情况下使注射工作)

模块文件:

import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';

@NgModule({
    imports: [ ... ],
    declarations: [ ... ],
    providers: [
        { provide: 'VIEW_CONFIG', useValue: viewConfig },
        DataService,
    ]})
   export class Section1Module { }

部分文件:

@Injectable()
export class DataService {

    constructor(@Inject('VIEW_CONFIG') private viewConfig : any) {}

}

解决方案2:工厂提供商

Not working after ng serve reboot (see update)

灵感来自https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#factory-provider
模块文件:从'../services/data.service'导入
;
从'./view.config.json'导入viewConfig;

export let VIEW_CONFIG = new InjectionToken <any>('');
let dataServiceFactory =(configObject):DataService => {
返回新的DataService(configObject)
}

@NgModule({
进口:[...],
声明:[...],
提供者:[
{provide:VIEW_CONFIG,useValue:viewConfig},
{
提供:DataService,
useFactory:dataServiceFactory,
deps:[VIEW_CONFIG]
},
]})
导出类Section1Module {}
部分文件:@Injectable()
导出类DataService {

构造函数(private viewConfig:any){}

}
解决方案3:具有直接实例化的自定义提供程序

Not working after ng serve reboot (see update)

模块文件:
从'../services/data.service'导入
;
从'./view.config.json'导入viewConfig;

@NgModule({
进口:[...],
声明:[...],
提供者:[
{provide:DataService,useValue:new DataService(viewConfig)},
]})
导出类Section1Module {}
部分文件:@Injectable()
导出类DataService {

构造函数(private viewConfig:any){}

}
解决方案4:自定义提供商与工厂

Not working after ng serve reboot (see update)

与解决方案3非常相似......
模块文件:从'../services/data.service'导入
;
从'./view.config.json'导入viewConfig;

让dataServiceFactory =(configObject)=> {return new DataService(configObject)}

@NgModule({
进口:[...],
声明:[...],
提供者:[
{provide:DataService,useValue:dataServiceFactory(viewConfig)}
]})
导出类Section1Module {}
部分文件:@Injectable()
导出类DataService {

构造函数(private viewConfig:any){}

}

Solution 5 使用从服务文件AND和注入令牌导出的工厂

模块文件:

export const VIEW_CONFIG = new InjectionToken<any>('');

 @NgModule({
    imports: [ ... ],
    declarations: [ ... ],
    providers: [
         { provide: VIEW_CONFIG, useValue: viewConfig },
         { provide : DataService,
           useFactory: dataServiceFactory,
           deps : [VIEW_CONFIG] }
    ]})
   export class Section1Module { }

部分文件:

@Injectable()
export class DataService {
    constructor(private viewConfig : any) {}
}

export function dataServiceFactory(configObject) {
    return new DataService(configObject);
}

我对“什么是正确的解决方案?”的批评,想法,任何形式的新领导都持开放态度 . 甚至“这些是正确的解决方案吗?”

非常感谢 ! :d


UPDATE 有一次,我意识到我的Angular-CLI行为异常,并且在杀死CLI本地服务器并重新启动它之后,其中一些方法没有工作,但下次我保存文件并重新编译CLI时,它可以正常工作精细...

Solution 1 :还在工作

Solution 2 / Solution 3 :失败并显示错误:

Error encountered resolving symbol values statically. Calling function 
'DataService', function calls are not supported. Consider replacing the 
function or lambda with a reference to an exported function

Solution 4 :失败并显示错误:

Error encountered resolving symbol values statically. Reference to a non-exported function

Added solution 5

1 回答

  • 1

    我使用视图的配置数据的方法是这样的:

    My config file:

    export const IBO_DETAILS_GENERAL = {
        iboCode: 'IBOsFormCodeField',
        iboGivenName: 'IBOsFormGivenNameField',
        iboFamilyName: 'IBOsFormFamilyNameField',
        iboEmail: 'IBOsFormEmailField',
    };
    
    export const IBO_DETAILS_ACCOUNT = [];
    

    My view component:

    import { IBO_DETAILS_GENERAL } from './ibo-details-formfields';
    
    @Component({
        selector: 'ibo-details-general',
        templateUrl: './ibo-details-general.component.html',
        styles: [],
    })
    export class IboDetailsGeneral extends FilterDataMappingManipulator implements OnInit, OnDestroy {
        // Initial constants,vectors and component mapping
        private formFields = IBO_DETAILS_GENERAL;
    

    所以,这样,我在 formFields 中有 config . 我可以在这个组件的范围内的任何地方使用它 .

    我目前正在使用它来生成动态表单字段(输入,选择等),具体取决于我从API调用中获取的数据 .

    但您可以使用该对象(在我的情况下为 formFields )来查找您需要的内容并将其作为参数发送到您的服务 .

    此外,将共享服务放在更高级别上也做得很好 . 我相信这是最好的方法 . 但是我不会在每个组件上添加它到 providers ,我会添加它组件的模块 . 像这样:

    @NgModule({
        declarations: [
            ChildComp1,
            ChildComp2
        ],
        imports: [
        ],
        providers: [
            SharedService
        ]
    })
    export class SectionModule {
    }
    

    这样, ChildComp1ChildComp2 将可以访问 SharedService 而无需在组件代码中添加它 .

    例如,当您定义用户的部分时,这可以正常工作 . 在里面,你说 UsersModule 你在 providers 中声明你的 UsersSharedService 然后在 declarations 你声明你的 UsersLeftPanelUsersRightPanel (例子) .

    Update 1:

    服务中配置的使用示例 .

    想象共享服务有这个方法:

    getData() {
      // do Stuff
      let myData = {}; // Result of the stuff we did
      this.dataSubject.next(myData);
    }
    

    在您的组件中,您可以这样调用:

    this.myService.getData();
    

    对?

    现在,请记住我们已经声明了配置?将其添加到通话中 .

    this.myService.getData(this.formFields);
    

    并且,在我们的服务中:

    getData(currentConfig) {
          // do Stuff depending on currentConfig obj received as parameter
          let myData = {}; // Result of the stuff we did
          this.dataSubject.next(myData);
        }
    

    这样,您调用我们的共享服务的 getData() 方法传递不同的配置 . 这样,您就不必在许多 providers 中包含您的服务,并且您不必复制/粘贴处理配置的逻辑,您可以在共享服务中使用它,因此,您的所有孩子都可以访问它 .

    Update 2:

    按照解决方案5的方法,我认为你错过了 multi: true .

    试试这个:

    export function dataServiceFactory(configObject) {
        return () => new DataService(configObject);
    }
    
    providers: [
         { provide: VIEW_CONFIG, useValue: viewConfig },
         { provide : DataService,
           useFactory: dataServiceFactory,
           deps : [VIEW_CONFIG],
           multi: true }
    ]})
    

    导出函数中的 return 是关键: return () => .

    这是我在我的项目中的方式:

    export function initConfigFactory(userConfig: UserConfig) {
        return () => userConfig.getUsersConfig();
    }
    

    userConfig.getUsersConfig() 是获取用户配置的服务调用 .

    providers: [
        {
            provide: APP_INITIALIZER,
            useFactory: initConfigFactory,
            deps: [UserConfig],
            multi: true
        }
    ]
    

    这非常接近你的解决方案5,试一试!

相关问题