I've just started on TypeScript, so I think it is something very silly. I've gone through couple of dozens links but can't find exactly what is the issue that my service instance is undefined. So my app structure is simple(?): Using AngularJS 1.5 with TypeScript and Webpack. My Main app file is as below:
// External
import ng = require("angular");
// App modules
import authIntSvc = require("./security/authInterceptorSvc");
// Note: Can't use require as it returns object and we need function
import localStorageHandler from "./core/localStorageCfg";
import routingHandler from "./uiRoutes";
export
let ptaToolsApp = ng.module('ptaToolsApp', [
'ngRoute', 'ngStorage',
'ptaTools.CoreMod'
]);
ptaToolsApp
.config(routingHandler)
.config(localStorageHandler);
console.info("All Done...! " + new Date());
// Add services
import secSvc = require("./security/SecuritySvc");
ptaToolsApp.service(secSvc.SecuritySvc.IID, secSvc.SecuritySvc);
//import { interceptorInitiator } from "./security/authInterceptorSvc";
ptaToolsApp.service(authIntSvc.authInterceptorSvc.IID, authIntSvc.authInterceptorSvc);
ptaToolsApp.config(authIntSvc.interceptorInitiator);
// Add module controlles - TODO: FInd better way
import {
HomeCtrl
}
from "./userHome/homeCtrl";
ptaToolsApp.controller(HomeCtrl.IID, HomeCtrl);
// App Init --------- Run function ---------------------------------------
function runApp(authSvc: secSvc.SecuritySvc) {
authSvc.checkAuthData();
}
runApp.$inject = [secSvc.SecuritySvc.IID];
// Run App
ptaToolsApp.run(runApp);
// App Init --------- Run function ---------------------------------------
// Dummy requires, just needed for WebPack to pack it in bundle
import coreMod = require("./core/coreModule");
const a1 = coreMod;
import ngRoute = require("angular-route");
const a2 = ngRoute;
import ngStorage = require("ngstorage");
const a3 = ngStorage;
My Interceptor file is as below:
import ng = require("angular");
import {
appLocalStorageSvc
}
from "../core/appLocalStorageSvc";
import * as secModels from "./models";
// implements ng.IHttpInterceptor
export class authInterceptorSvc {
public static readonly IID = "sec.authInterceptorSvc";
static $inject = ['$location', '$q', appLocalStorageSvc.IID];
constructor(private $location: ng.ILocationService, private $q: ng.IQService, private appLocalStorage: appLocalStorageSvc) {
console.info('constructor:: ' + authInterceptorSvc.IID);
}
//public request(reqCfg: ng.IRequestConfig): ng.IRequestConfig {
public request(reqCfg: any): any {
reqCfg.headers = reqCfg.headers || {};
// if ((this.appLocalStorage.authData) && (this.appLocalStorage.authData.isAuth === true))
// reqCfg.headers.Authorization = 'Bearer ' + this.appLocalStorage.authData.oAuthToken;
console.info("in authInterceptorSvc.request");
console.debug(reqCfg);
console.debug(JSON.stringify(this));
return reqCfg;
}
// HTTP Rejection
public responseError(rejection: any) {
if (rejection.status === 401) {
this.$location.path('/login');
return this.$q.reject(rejection);
}
return this.$q.reject(rejection);
}
}
export
function interceptorInitiator($httpProvider: ng.IHttpProvider) {
$httpProvider.interceptors.push(authInterceptorSvc.IID);
}
interceptorInitiator.$inject = ["$httpProvider"];
So, in above method request(reqCfg: any): any I've commented lines where I need to access local variable for appLocalStorage, I get error that "can't access property 'appLocalStorage' of undefined".
** I added console.log in all my service constructors (will remove later). When I page load my app loads fine till interceptor is hit. In the request function my service instance is undefined. See the log below:
I've highlighted the "undefined" as a result of console.debug(JSON.stringify(this));
I'm wondering why my this in service is undefined.
Another not a big issue, I think, just practice, if you see those dummy lines in the end of main app file. Why do I need to tell webpack something that basic?
Can someone pls help?
As my answer below the main issue is solved
But the minor issue of putting dummy lines so that webpack bundles my files still stays.
After doing more digging, I found the answer here: (The question was almost same as mine) TypeScript interceptor in AngularJS
So the issue was how interceptor works differently than controller or services.
You need to make it objectify (as explained in the answer in above post).
public request = (config) => {
// this.TokenService is undefined here as well as $window or $q which I tried to inject
config.headers = config.headers || {};
if (this.TokenService.Token != "")
config.headers.Authorization = 'Bearer ' + this.TokenService.Token;
return config;
}
As shown above works fine.