'Spartacus : Access Occ url on the NgModule inside Spartacus.configuration.module.ts file
I have experience on Jquery but Angular is very new to me and so is spartacus. I have been trying to configure our Spartacus to be used across multiple environments. The only solution that I could find was to use the meta tag on index.html and then grab the config based on url as mentioned by janwidmer and CarlEricLavoie. I did make a slight change from these 2 solutions though, and that was to use the environment.{env}.ts files instead of a new Backend service or keeping the config in a map in the same file.
The issue that I am facing is that the spartacus.cofniguration.module.ts file needs these values in @NgModule and I've tried everything that I could think of, but am unable to use the value of this.config.backend?.occ?.baseUrl inside the NgModule, where I need to give the value for base URL and Base site.
Below is what I am trying to do. i have written the logic that would expose the correct config object according to the OCC base url that I receive on the environment. Now over here, the console log inside the constructor prints a proper object with all the properties I need, but then the conf object right before the @NgModule, it prints undefined and the values inside the NgModule are undefined as well then.
I also tried to create a new class and import it here so I could maybe create an instance, but couldn't do that as well, as it would then need the variable/method to be static for me to be able to access it inside NgModule.
import { Injectable, NgModule } from '@angular/core';
import { FacetChangedEvent, FeaturesConfig, I18nConfig, OccConfig, provideConfig, SiteContextConfig } from "@spartacus/core";
import { environment } from '../../environments/environment';
import { defaultB2bCheckoutConfig, defaultB2bOccConfig } from "@spartacus/setup";
import { defaultCmsContentProviders, layoutConfig, mediaConfig } from "@spartacus/storefront";
import { translations } from 'src/assets/i18n-translations/translations';
import { translationChunksConfig } from 'src/assets/i18n-translations/translation-chunks-config';
import { CdcConfig, CdcRootModule, CDC_FEATURE } from '@spartacus/cdc/root';
import { EnvironmentConfigurationModule } from "../../environments/environment-configuration.module"
import { environment as envdev} from '../../environments/environment';
import { environment as envstag} from '../../environments/environment.stage';
import { environment as envprod} from '../../environments/environment.prod';
let conf : any;
console.log("before ng");
console.log(conf);
@NgModule({
declarations: [],
imports: [
],
providers: [provideConfig(layoutConfig), provideConfig(mediaConfig), ...defaultCmsContentProviders, provideConfig(<OccConfig><unknown>{
backend: {
occ: {
baseUrl: environment.baseUrl,
}
},
}), provideConfig(<SiteContextConfig>{
context: {
urlParameters: ['baseSite', 'language', 'currency'],
baseSite: [environment?.baseSite],
currency: ['USD', 'GBP',]
},
}),
provideConfig(<I18nConfig>{
i18n: {
backend:{
loadPath:'assets/i18n-translations/{{lng}}/{{ns}}.ts',
},
resources: translations,
chunks: translationChunksConfig
,fallbackLang: 'en'
},
}
), provideConfig(<FeaturesConfig>{
features: {
level: '4.2'
}
}),
provideConfig(defaultB2bOccConfig), provideConfig(defaultB2bCheckoutConfig),
]
})
export class SpartacusConfigurationModule {
urlValue : string | undefined;
env: any;
constructor(private config: OccConfig) {
this.urlValue = this.config.backend?.occ?.baseUrl;
console.log("baseurl : " + this.config.backend?.occ?.baseUrl);
if(this.urlValue?.includes('s1'))
{
this.env=envstag;
}
else if(this.urlValue?.includes('p1'))
{
this.env=envprod;
}
else{
this.env=envdev;
}
conf = this.env;
console.log("conf");
console.log(conf);
}
getConfig() {
return conf;
}
}
Apart from these solutions, we have also tried to use window.location and location.href to find the base url and work based on that. This works amazing on local, but as soon as you deploy it to the server, it says that the reference window not found/reference location not found. We tried to do this right before the NgModule, inside spartacus-configuration.module.ts
import { environment as envDev } from "../../environments/environment";
import { environment as envStage } from "../../environments/environment.stage";
import { environment as envProd } from "../../environments/environment.prod";
let loc=location.hostname;
let env;
if(loc.includes('s1'))
{
env=envStage;
}
else if(loc.includes('p1'))
{
env=envProd;
}
else{
env=envDev;
}
console.log("before ng===>>>",loc);
Solution 1:[1]
With environment imports, your standard build configuration will replace the environment.ts variables with the ones set by your server's environment (eg. process.env) before deployment. Therefore, you should only import from environment.ts in your code and let the server handle overriding the staging environment variables.
With location and window objects, they are not accessible on the server-side of the build because Angular Universal initially delivers a pre-rendered page readable by bots (usually html-only) for SEO purposes. The location and window objects do not exist in this instance. In Angular, window and location objects should be imported into your classes.
Use Window: https://stackoverflow.com/a/52620181/12566149
Use Location: https://stackoverflow.com/a/43093554/12566149
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Caine Rotherham |
