简体   繁体   中英

Passing dynamic object to an angular module's forRoot()

I'm using the package ngx-cookieconsent which imports the module as:

const cookieConfig: NgcCookieConsentConfig = { "cookie": { "domain": "localhost" }, ... "theme": "block", "content": { "policy": "Cookie Policy" } }; ... @NgModule({ imports: [ NgcCookieConsentModule.forRoot(cookieConfig) ]

However, the domain property on the config will be set at runtime and so I can't have this defined as a constant. To get round this I have done the following:

Created a ConfigurationService that gets the config and stores it:

@Injectable()
export class ConfigurationService {

  private configuration: IServerConfiguration;

  constructor(private http: HttpClient, @Inject('BASE_URL') private baseUrl: string) { }

  loadConfig() {
    return this.http.get<IServerConfiguration>(this.baseUrl + 'Configuration')
      .pipe(
        tap(config => {
          this.configuration = <IServerConfiguration>(config);
        })
      )
      .toPromise();
  }

  public domain(): string {
    return this.configuration.domain;
  }
}

And this is set up as an APP_INITIALIZER so that the config is called first:

export function loadConfiguration(configService: ConfigurationService) {
  return () => configService.loadConfig();
}

...
 providers: [
    ConfigurationService,   
    {
      provide: APP_INITIALIZER,
      useFactory: loadConfiguration,
      multi: true,
      deps: [ConfigurationService]
    }],

And then have created a class to create my cookieConsentOptions object using the config:

@Injectable()
export class CookieConstentService {

  cookieDomain: string;

  constructor(configService: ConfigurationService) {
    this.cookieDomain = configService.domain();
  }

  get cookieConstentOptions(): NgcCookieConsentConfig {
    return {
      "cookie": {
        "domain": this.cookieDomain
      },
      "position": "top-right",      
      "content": {
        "message": "This website uses cookies to ensure you get the best experience on our website."
      }
    };
  }

Issue

I've got the dependency set up between the configService and the CookieConstentService so that I only create the the cookie options when I have the config values.

However, I am unsure how to pass a dynamic value to the .forRoot() of a module. I should be able to do cookieConsentService.cookieConstentOptions() to get the object but I'm not sure where to instantiate this to be used in he module import. It takes a dependency so can't just create a new instance myself.

Any ideas how I effectively inject a method into a 3rd party module's forRoot() ?

Thanks

After posting this question I learnt that the object passed into the forRoot() method is essentially a singleton, so if I set any values before it gets initialised then it will use this. The way I implemented this was:

  1. Create an instance of the options with the constant/default settings (these won't change between environments):
import { NgcCookieConsentConfig } from "ngx-cookieconsent";

export const cookieConsentOptions: NgcCookieConsentConfig  =
{
  "cookie": {
    "domain": "not-set"
  },
  "position": "bottom-right",
  "theme": "block",
  "palette": {
    "popup": {
      "background": "#df1010",
      "text": "#ffffff",
      "link": "#ffffff"
    },
    "button": {
      "background": "#ffffff",
      "text": "#000000",
      "border": "transparent"
    }
  },
  "type": "info",
  "content": {
    "message": "This website uses cookies to ensure you get the best experience on our website.",
    "dismiss": "Got it!",
    "deny": "Refuse cookies",
    "link": "Learn more",
    "href": "/cookie-policy",
    "policy": "Cookie Policy",
    "target": "_self"
  } 
};

Add an APP_INITIALIZER to the appModule which injects the NgcCookieConsentConfig object. This will pass in the object created above:

...
{
      provide: APP_INITIALIZER,
      useFactory: cookieConfigFactory,
      deps: [HttpClient, NgcCookieConsentConfig, ConfigurationService],
      multi: true
    },
...
  1. And create the method the used above:
export function cookieConfigFactory(http: HttpClient, config: NgcCookieConsentConfig, configService: ConfigurationService) {
  return () => configService.loadConfig().then(x => config.cookie.domain = x.domain)
}

I'm getting the value for the cookie domain from a custom config service hence why it's being injected in, yours might be different.

  1. Finally in the modules import in appModules, import the CookieConsent module passing in the object created in the first step:
NgcCookieConsentModule.forRoot(cookieConsentOptions)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM