App.settings - the Angular way?
I figured out how to do this with InjectionTokens (see example below), and if your project was built using the Angular CLI you can use the environment files found in /environments
for static application wide settings like an API endpoint, but depending on your project's requirements you will most likely end up using both since environment files are just object literals, while an injectable configuration using InjectionToken
's can use the environment variables and since it's a class can have logic applied to configure it based on other factors in the application, such as initial HTTP request data, subdomain, etc.
Injection Tokens Example
/app/app-config.module.ts
import { NgModule, InjectionToken } from '@angular/core';
import { environment } from '../environments/environment';
export let APP_CONFIG = new InjectionToken<AppConfig>('app.config');
export class AppConfig {
apiEndpoint: string;
}
export const APP_DI_CONFIG: AppConfig = {
apiEndpoint: environment.apiEndpoint
};
@NgModule({
providers: [{
provide: APP_CONFIG,
useValue: APP_DI_CONFIG
}]
})
export class AppConfigModule { }
/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppConfigModule } from './app-config.module';
@NgModule({
declarations: [
// ...
],
imports: [
// ...
AppConfigModule
],
bootstrap: [AppComponent]
})
export class AppModule { }
Now you can just DI it into any component, service, etc:
/app/core/auth.service.ts
import { Injectable, Inject } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import { APP_CONFIG, AppConfig } from '../app-config.module';
import { AuthHttp } from 'angular2-jwt';
@Injectable()
export class AuthService {
constructor(
private http: Http,
private router: Router,
private authHttp: AuthHttp,
@Inject(APP_CONFIG) private config: AppConfig
) { }
/**
* Logs a user into the application.
* @param payload
*/
public login(payload: { username: string, password: string }) {
return this.http
.post(`${this.config.apiEndpoint}/login`, payload)
.map((response: Response) => {
const token = response.json().token;
sessionStorage.setItem('token', token); // TODO: can this be done else where? interceptor
return this.handleResponse(response); // TODO: unset token shouldn't return the token to login
})
.catch(this.handleError);
}
// ...
}
You can then also type check the config using the exported AppConfig.
appsettings.json file loading after app init on APP_INITIALIZER
So everything was well configured except from one important thing: Constructors are used only to inject dependencies. So at that point, I cannot make this:
constructor(private readonly httpClient: HttpClient,
private configService: ConfigService) {
this.apiUrl = this.configService.apiBaseUrl;
}
SOLUTION
I removed then the line inside the constructor:
constructor(private readonly httpClient: HttpClient,
private configService: ConfigService) {
}
And just called the apiBaseUrl
wherever I needed it and it worked:
public get<T>(url: string): Observable<T> {
return this.httpClient.get<T>(`${this.configService.apiBaseUrl}${url}`);
}
Trying to set environment variables in appSettings.json - Angular and Typescript
As stated in comment, appsettings.json is not for angular application. here you can go through this tutorial to find necessary steps for using enviornment.
here are some quick steps:
import { environment } from './../environments/environment';
...
const baseUrl: string = environment.baseUrl;
where environment.ts may look like
export const environment = {
production: false,
baseUrl: "http://localhost:45644/api/",
};
live example here
How do I create an app specific configuration for Angular with NX/Nrwl?
From what I can understand, IMHO, you should keep DefaultAppConfig
in shared/config
and CarAppConfig
in app-car
.
Reason: As the name suggest, shared is shared by all libs. So, why should other app have access to an object which is out of its scope.
You can extend
DefaultAppConfig
in all apps and use it in its app-car.module
or something.
Side note: You can also explore the concept of Tags to have more control over what can be imported into a lib and what should not.
Please let me know if I get it correctly.
Related Topics
Three.Js:2Xmeshes Using Same Vector as Position
Jquery Function to Get All Unique Elements from an Array
How to Store a JavaScript Function in JSON
JavaScript Functions Like "Var Foo = Function Bar() ..."
Typeerror: _Firebase_Webpack_Imported_Module_2_.Default.Collection Is Not a Function
Array.Push() Makes All Elements the Same When Pushing an Object
How to Filter Array When Object Key Value Is in Array
JavaScript - Are Dom Redraw Methods Synchronous
How to Implement Custom Sort to a Specific Column After Jqgrid Has Been Generated
How to Declare a Global Variable in a .Js File
Uncaught Typeerror: Cannot Read Property 'Value' of Undefined
Is It Evil to Use Eval to Convert a String to a Function
Access Object Properties Within Object
Higher-Order Functions in JavaScript