我打电话给你,告诉你在这里使用什么方法:我已经测试了很多东西来解决我的问题,我至少有4个工作解决方案,但我不知道哪个(s) )是最好的,如果其中一些只是因为我所做的其他事情的副作用而不能使用......
我无法在文档中找到任何指向这些解决方案(或其他解决方案)的内容
首先,我的情况:我正在构建一个连接到数据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
我尝试了多个似乎在部分模块文件中工作的东西:
解决方案1:注射
(即使我没有在任何地方看到这一点,我也无法在没有引号的情况下进行注射工作)
模块文件:
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:工厂提供商
ng服务重新启动后无效(请参阅更新)
灵感来自https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#factory-provider
模块文件:
import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';
export let VIEW_CONFIG = new InjectionToken<any>('');
let dataServiceFactory = (configObject):DataService => {
return new DataService(configObject)
}
@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) {}
}
解决方案3:具有直接实例化的自定义提供商
ng服务重新启动后无效(请参阅更新)
模块文件:
import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers: [
{ provide: DataService, useValue : new DataService(viewConfig) },
]})
export class Section1Module { }
部分文件:
@Injectable()
export class DataService {
constructor(private viewConfig : any) {}
}
解决方案4:带工厂的自定义提供商
ng服务重新启动后无效(请参阅更新)
与解决方案3非常相似......
模块文件:
import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';
let dataServiceFactory = (configObject) => { return new DataService(configObject) }
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers: [
{ provide: DataService, useValue : dataServiceFactory(viewConfig) }
]})
export class Section1Module { }
部分文件:
@Injectable()
export class DataService {
constructor(private viewConfig : any) {}
}
解决方案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);
}
我对任何批评,想法,任何形式的新领导都持开放态度。&#34;什么是正确的解决方案?&#34;甚至&#34;这些是正确的解决方案吗?&#34;
非常感谢! :d
更新 有一次,我意识到我的Angular-CLI表现得很奇怪,如果我杀了我的本地服务器并且做了一个&#34; ng服务&#34;那么这些方法中的一些并不起作用。 甚至更奇怪的是,在杀死CLI本地服务器并重新启动它之后它没有工作,但下次我保存文件并重新编译CLI时,它工作正常......
解决方案1 :仍然有效
解决方案2 /解决方案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
解决方案4 :失败并显示错误:
Error encountered resolving symbol values statically. Reference to a non-exported function
添加解决方案5
答案 0 :(得分:2)
我使用视图配置数据的方法是:
我的配置文件:
export const IBO_DETAILS_GENERAL = {
iboCode: 'IBOsFormCodeField',
iboGivenName: 'IBOsFormGivenNameField',
iboFamilyName: 'IBOsFormFamilyNameField',
iboEmail: 'IBOsFormEmailField',
};
export const IBO_DETAILS_ACCOUNT = [];
我的观看组件
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;
所以,这样,我在config
中拥有formFields
。我可以在这个组件的范围内的任何地方使用它。
我目前正在使用它来生成动态表单字段(输入,选择等),具体取决于我从API调用中获取的数据。
但您可以使用该对象(在我的情况下为formFields
)来查找您需要的内容并将其作为参数发送给您的服务。
此外,将共享服务放在更高级别上也做得很好。我相信这是最好的方法。但我不会在每个组件上将它添加到providers
,我会将其添加到组件的模块上。像这样:
@NgModule({
declarations: [
ChildComp1,
ChildComp2
],
imports: [
],
providers: [
SharedService
]
})
export class SectionModule {
}
这样,ChildComp1
和ChildComp2
可以访问SharedService
,而无需在组件代码中添加它。
例如,当您定义 User 的部分时,这可以正常工作。在内部,例如UsersModule
,您在providers
UsersSharedService
中声明,然后在declarations
中声明您的UsersLeftPanel
和UsersRightPanel
(实施例)
更新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
中包含您的服务,并且您不必复制/粘贴处理配置的逻辑,您可以在共享服务中使用它因此,你所有的孩子都可以访问它。
更新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
}
]
这非常接近您的 Solution 5 ,试一试!