Angular aot build: dynamic forRoot parameter results in undefined

杀马特。学长 韩版系。学妹 提交于 2020-05-13 07:03:20

问题


I need to send a configuration (array of objects) to a service in a feature module and this configuration needs to be dynamically calculated. I used forRoot and it worked fine until I've built it with --aot.

problem: With --aot, the configuration results in undefined.

Here is a link to an example I made on stackblitz: https://stackblitz.com/edit/angular-aot-forroot-error

!! it works as desired on stackblitz, since it is not built with aot !! If you build it locally with aot, though, the GetConfigService will throw an error since config will be undefined.

Important parts:

AppModule:

export const config = [
  {
    id: 'first'
  },
  {
    id: 'second'
  }
];

// just illustrative modification (in my project I need to modify config based on environment)
export function modifyConfig(config) {
  return config.map(c => c.id === 'first' ? {...c, default: true} : c);
}

const configModified = modifyConfig(config);

@NgModule({
  imports:      [
    BrowserModule,
    WithParametersdModule.forRoot(configModified)
  ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

WithParametersdModule:

@NgModule()
export class WithParametersdModule {
  static forRoot(config) {
    return {
      ngModule: WithParametersdModule,
      providers: [
        {
          provide: SOME_CONFIG,
          useValue: config
        },
        GetConfigService
      ]
    }
  }
}

GetConfigService:

@Injectable()
export class GetConfigService {

  constructor(@Inject(SOME_CONFIG) private config) {}

  get configObj() {
    if (!this.config) {
      throw `config: ${this.config}`;
    }

    return this.config;
  }
}

Thanks for help or explanation of what am I doing wrong.


回答1:


I found that it might be because AOT would try to replace useValue at compile time but when you pass these values at runtime so AOT just replace it with undefined. The solution is use useFactory instead of useValue. This solved this problem.

Here is what I did:

// Declare a function type which returns the config
export type ConfigFunction = () => any;

// Replace useValue with useFactory
@NgModule()
export class WithParametersdModule {
  static forRoot(config: {
    func: ConfigFunction,
    // You could add other config parameters here...
  }) {
    return {
      ngModule: WithParametersdModule,
      providers: [
        {
          provide: SOME_CONFIG,
          useFactory: config.func
        },
        GetConfigService
      ]
    }
  }
}

Then you can use it as following:

export function getConfig(): any {
  return {
    id: 'first'
  },
  {
    id: 'second'
  };
}

@NgModule({
  // ...
  imports: [
    BrowserModule,
    WithParametersdModule.forRoot({ func: getConfig }),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


来源:https://stackoverflow.com/questions/50131083/angular-aot-build-dynamic-forroot-parameter-results-in-undefined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!