Reputation: 383
I have a big Angular application which is still needed in development, but already ready for use in production, I want to be switch between the states with simple change of
isProduction: boolean = false
to true, I did it by making apiHelperService which is just usual service, it works fine for most application:
import {Injectable} from "@angular/core";
import {Response, Http, Headers, RequestOptions} from "@angular/http";
import {Observable} from "rxjs/Observable";
@Injectable()
export class ApiHelperService {
productionURL: string = 'http://35.203.121.40';
developmentURL: string = 'http://10.25.37.523';
serverUrl: string;
apiPort: string = ':3000/';
socketPort: string = ':2000/';
isProductionMode: boolean = false;
constructor() {
this.serverUrl = this.isProductionMode ? this.productionURL : this.developmentURL;
}
getApiURL(): string {
return this.serverUrl + this.apiPort;
}
getSocketUrl(): string {
return this.serverUrl + this.socketPort;
}
getApiIp(): string {
const serverIp = this.isProductionMode ? this.productionURL.split(':')[0] : this.developmentURL.split(':')[0];
console.log('string url is:', serverIp);
return serverIp;
}
serialize(obj) {
var str = [];
for (var p in obj) {
if (obj.hasOwnProperty(p) && ((obj[p] != null && obj[p] != '') || (typeof obj[p] == "boolean"))) {
if (obj[p].length == 0) {
continue;
}
else if (obj[p].length > 1 && typeof obj[p] == 'object') { // reformats arrays
for (let i = 0; i < obj[p].length; i++) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p][i]));
}
}
else {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
}
}
return '?' + str.join("&");
}
extractData(res: Response) {
let body = res.json();
// console.log("body", body)
return body || {};
}
handleError(error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
BUT i have socket library that configures the socket URL in the
app.module.ts
so when I try to use dynamic URL(in the app.module.ts) like this:
const apiHelper = new ApiHelperService(); //fails here
const url: string = apiHelper.getSocketUrl();
const config: SocketIoConfig = { url: url, options: {
"force new connection" : true,
"reconnectionAttempts": "Infinity",
"timeout" : 10000,
"transports" : ["websocket"]} };
it fails with this error:
ERROR in Error: Error encountered resolving symbol values statically. Calling
function 'ApiHelperService', function calls are not supported. Consider replacing the function or lambda with a
reference to an exported function, resolving symbol AppModule
so my question is, is my approach wrong? what is the right approach to handle this problem?
Upvotes: 4
Views: 8899
Reputation: 407
it works in different way: alligator.io/angular/environment-variables
you must specify variables in environment.ts and environment.prod.ts
then import {environment} from '../../environments/environment'; environment object will contain proper variables
Upvotes: 6