6

We're well aware that there are various ways of setting config for imported modules. We have '.forRoot()', 'useValue', 'useClass' and such to be used in the importing module.

Say for example, we want to use ng2-currency-mask. Taking directly from its example usage in the documentation, we can set the configuration for CurrencyMaskModule by doing this in the importing module (AppModule in this case):

export const CustomCurrencyMaskConfig: CurrencyMaskConfig = {
    align: "right",
    allowNegative: true,
    decimal: ",",
    precision: 2,
    prefix: "Module$ ",
    suffix: "",
    thousands: "."
};

@NgModule({
    imports: [
        ...
        CurrencyMaskModule
    ],
    declarations: [...],
    providers: [
        { provide: CURRENCY_MASK_CONFIG, useValue: CustomCurrencyMaskConfig }
    ],
    bootstrap: [AppComponent]
})
export class AppModule {}

However, if you want to set the config/useValue dynamically (e.g. a Settings page), we have to change it from within a component. Now I tested doing so with the following code written directly in the AppComponent:

import { Component, OnInit, Inject } from '@angular/core';
import { CURRENCY_MASK_CONFIG, CurrencyMaskConfig } from 'ng2-currency-mask/src/currency-mask.config';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  title = 'Testing Config App';

  constructor(
    @Inject(CURRENCY_MASK_CONFIG) ng2CurrencyMaskConfig: CurrencyMaskConfig,
  ) {
    // test
    ng2CurrencyMaskConfig =  {
      align: 'right',
      allowNegative: false,
      decimal: '.',
      precision: 5,
      prefix: 'Component$$$ ',
      suffix: '',
      thousands: ','
    };
  }

  ngOnInit() {
  }
}

Unfortunately, the change did not reflect to the components using ng2-currency-mask and the config set from the AppModule (the one with "Module$ " as prefix) is still what is working.

How do you successfully override/set a module's config from within a component?

UPDATE:

I have tried using ReflectiveInjector's resolve and fromResolvedProviders methods which doesn't also work:

import { Component, OnInit, ReflectiveInjector, Injector } from '@angular/core';
import { CURRENCY_MASK_CONFIG, CurrencyMaskConfig } from 'ng2-currency-mask/src/currency-mask.config';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  title = 'Testing Config App';

  constructor(
    private injector: Injector,
  ) {
  }

  ngOnInit() {
     // test
     const ng2CurrencyMaskConfig: CurrencyMaskConfig =  {
      align: 'right',
      allowNegative: false,
      decimal: '.',
      precision: 3,
      prefix: 'TESTR$ ',
      suffix: '',
      thousands: ','
    };

    const providers = ReflectiveInjector.resolve([{ provide: CURRENCY_MASK_CONFIG, useValue: ng2CurrencyMaskConfig }]);
    ReflectiveInjector.fromResolvedProviders(providers, this.injector);
  }
}

And using Static Injector doesn't work:

Injector.create(
[
    { 
        provide: CURRENCY_MASK_CONFIG, 
        useValue: ng2CurrencyMaskConfig 
    }
], 
this.injector);

Side Note: I'm well aware of an alternative solution for this specific module (CurrencyMaskModule) where we can actually just make a provider with a mutable property that will hold the CurrencyMaskConfig value. But this will leave me forced to change all input fields to add an attribute options to all the input fields using the currencyMask directive. In other words, I will be inserting something like [options]="myConfigProvider.currencyMaskConfig" in all those inputs needing it. I'm hoping to see a better/ more elegant way of doing this.

Cold Cerberus
  • 1,685
  • 14
  • 35
  • I have a similar dilemma and I'm curious on how this can be done. Have you considered using a [Factory provider](https://angular.io/guide/dependency-injection-providers#factory-providers) as a solution? – marckassay Jul 11 '19 at 16:48
  • No I haven't. I'd appreciate if someone could try it. Thanks for the idea. This post has been few months old and my code for this has been buried deep, lol. – Cold Cerberus Jul 16 '19 at 02:06

0 Answers0