Default values config using forRoot works in Dev but not in Prod (Aot)

919 Views Asked by At

The following code works fine in Dev, but not in Prod mode:

Module

export class SpinnerModule {
  static forRoot(config?: SpinnerConfig): ModuleWithProviders {
    return {
      ngModule: SpinnerModule,
      providers: [SpinnerService, { provide: SpinnerConfigToken, useValue: { ...DEFAULT_CONFIG, ...config } }]
    };
  }
}

Config Token

export const SpinnerConfigToken = new InjectionToken<SpinnerConfig>('SPINNER CONFIG TOKEN');

Model

// Project imports
import { Color, SpinnerAnimation } from '../../../models';

export interface SpinnerConfig {
  label?: string;
  color?: Color;
  animation?: SpinnerAnimation;
}

export const DEFAULT_CONFIG: SpinnerConfig = {
  label: '',
  color: Color.Blue,
  animation: SpinnerAnimation.DoubleBounce
};

Component

export class SpinnerComponent implements OnInit {
  @Input() isLoading: boolean;
  @Input() label: string;
  @Input() color: Color;
  @Input() animation: SpinnerAnimation;

  isFullScreen: boolean;
  spinnerAnimation: typeof SpinnerAnimation;

  constructor(@Inject(SpinnerConfigToken) private config: SpinnerConfig) {
    this.spinnerAnimation = SpinnerAnimation;
  }

  ngOnInit(): void {
    this.isLoading = !!this.isLoading;
    this.color = this.color || this.config.color;
    this.label = this.label || this.config.label;
    this.animation = this.animation || this.config.animation;

App module

@NgModule({
  imports: [
    ...
    SpinnerModule.forRoot({
      label: 'Loading, please wait ...'
    })
  ],
 ...
})
export class AppModule {}

I would like to merge the given config with what I've set as default values. what I've did works great in Dev, but in Prod, I've no errors, but the values are undefined, looks like the spread operator for merging the two object doesn't work,

Thanks a lot.

2

There are 2 best solutions below

0
Marcel Hoekstra On

You should create function to get at woring with an aot build.

export function DefaultConfig(config: HttpClient) {
  return ({ ...DEFAULT_CONFIG, ...config })
}

and:

providers: [SpinnerService, { provide: SpinnerConfigToken, useFactory: DefaultConfig }]
0
Youness Houdass On

Thanks Marcel, I was able to resolve it by using useFactory as I've said in comments, like this:

providers: [
   ToastService,
   { provide: ToastConfigToken, useValue: config },
   { provide: ToastConfigService, useFactory: defaultConfig, deps: [ToastConfigToken] }
]

export function defaultConfig(config: ToastConfig): any {
  return ({ ...DEFAULT_CONFIG, ...config })
}

But I would like something more simplier than using the two useValue and useFactory for a very basic functionality.