I know I'm not the only one having questions regarding this term. But the angular guys have about 23 questions regarding this term. I tried a lot of different things. One is important: I tried it the same way they do it for @angular/http
(exporting a bare factory function).
Fact is: it works - the code is not incorrect. But when I try to import the module I get this error:
ERROR in Error encountered resolving symbol values statically. Calling function
'TranslatorConfig', function calls are not supported. Consider replacing the
function or lambda with a reference to an exported function, resolving symbol
TranslatorModule.forRoot
When I run ng serve and touch the file after this error it recompiles without an error. But what ever I try to build (ng build -e prod --aot false
) I get this error and the build stops. I also get this error when I set "strictMetadataEmit": true
in tsconfig.json. I have a TranslatorModule.metadata.json
- this will not be the error.
Why it does not work? What does this error message mean in detail? What is the symbol value and why it has to be statically? How to get it to work?
For testing you can just install angular2-translator@2.0.0-alpha3. You can find the code on github: https://github.com/tflori/angular2-translator/tree/2.0
I just tried with these exported functions and different providers like below.
export function createTranslatorConfig(config: any = {}) {
return new TranslatorConfig(config);
}
export function createTranslator(translatorContainer: TranslatorContainer, module: string) {
return translatorContainer.getTranslator(module);
}
// ...
export class TranslatorModule {
public static forRoot(config: any = {}, module: string = "default"): ModuleWithProviders {
return {
ngModule: TranslatorModule,
providers: [
{ provide: "TranslatorConfigOptions", useValue: config },
{ provide: TranslatorConfig, useFactory: createTranslatorConfig, deps: [ "TranslatorConfigOptions" ] },
{ provide: "TranslatorModuleName", useValue: module },
{
provide: Translator,
useFactory: createTranslator,
deps: [ TranslatorContainer, "TranslatorModuleName" ],
},
],
};
}
}
The result is just another error message (now 'emakeDecorator' for symbol NgModule has a problem: ERROR in Error encountered resolving symbol values statically. Calling function 'ɵmakeDecorator', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol NgModule
I only have an answer to the last question. I still don't know what they mean with "symbol value" and the message is still confusing me.
At the end useValue can only be a value - you can not call a function here or before and give the result. And the factory that requires information need them from another provider.
The link from Babar helped me to come to this conclusion that works:
export const TRANSLATOR_GUARD: InjectionToken<string> = new InjectionToken("TRANSLATOR_GUARD");
export const TRANSLATOR_OPTIONS: InjectionToken<object> = new InjectionToken("TRANSLATOR_OPTIONS");
export const TRANSLATOR_MODULE: InjectionToken<string> = new InjectionToken("TRANSLATOR_MODULE");
@NgModule({
declarations: [
TranslatePipe,
TranslateComponent,
],
exports: [
TranslatePipe,
TranslateComponent,
],
imports: [HttpModule],
providers: [
TranslationLoaderJson,
TranslateLogHandler,
TranslatorContainer,
],
})
export class TranslatorModule {
public static forRoot(options: any = {}, module: string = "default"): ModuleWithProviders {
return {
ngModule: TranslatorModule,
providers: [
{
provide: TRANSLATOR_GUARD,
useFactory: guardTranslatorModule,
deps: [ [TranslatorConfig, new Optional(), new SkipSelf()]],
},
{ provide: TRANSLATOR_OPTIONS, useValue: options },
{ provide: TranslatorConfig, useFactory: createTranslatorConfig, deps: [ TRANSLATOR_OPTIONS ] },
{ provide: TRANSLATOR_MODULE, useValue: module },
{
provide: Translator,
useFactory: createTranslator,
deps: [ TranslatorContainer, TRANSLATOR_MODULE ],
},
],
};
}
public static forChild(module: string = "default") {
return {
ngModule: TranslatorModule,
providers: [
{ provide: TRANSLATOR_MODULE, useValue: module },
{
provide: Translator,
useFactory: createTranslator,
deps: [ TranslatorContainer, TRANSLATOR_MODULE ],
},
],
};
}
constructor(@Optional() @Inject(TRANSLATOR_GUARD) guard: any) {}
}
export function guardTranslatorModule(options: any): string {
if (options) {
throw new Error(
"Application called TranslatorModule.forRoot twice. For submodules use TranslatorModule.forChild instead.",
);
}
return "guarded";
}
export function createTranslatorConfig(config: any = {}) {
return new TranslatorConfig(config);
}
export function createTranslator(translatorContainer: TranslatorContainer, module: string) {
return translatorContainer.getTranslator(module);
}
What I posted in the question worked, too. I got this error because of linking the module to node_modules of the test project.
I'm still searching for an answer to the question: what they want from me? And why?