Typescript promise bind angular 1.5 - javascript

I am having a problem that my promise isn't being bound to the correct this.
I have read many articles on this subject and I think I understand the problem, but the solution isn't clear.
Suggestions
Here is the code:
// AngleCouch.ts`enter code here`
namespace AngleCouchDb {
//Note this is not a ng Service
export class AngleCouch {
...
public getAllUsers(): ng.IPromise<any> {
let dbUrl: string = this.urlPrefix + "/_users/_all_docs? include_docs=true";
let status = new CouchStatus();
console.log("in getAllUsers");
return this.http.get(dbUrl);
}
...
}
}
// UserManagementController.ts
module app {
class UserManagementController {
static $inject = [
'$mdSidenav', '$mdToast', '$mdDialog',
'$mdMedia', '$mdBottomSheet', '$state'];
...
public fetchUsers = () => {
let aUser = AngleCouchDb.ActiveUser.getInstance();
if (aUser.loginStatus `enter code here`!== Shows.StaticData.LoggedIn) {
return;
}
console.log("userManagementController: ");
console.log(this.$state);
this.vm.couch = new AngleCouchDb.AngleCouch();
this.vm.version = {};
this.vm.docTypeList = [];
this.vm.couch.urlPrefix = Shows.StaticData.server;
this.vm.user = new AngleCouchDb.UserCred();
this.vm.couch = new AngleCouchDb.AngleCouch();
this.vm.couch.getAllUsers().then(this.getAllUsersCB, (response: any) => {
console.log(response);`enter code here`
});
}
public getAllUsersCB = (response) => {
this.vm.gridObj = this.vm.initGridOpt();
this.vm.gridObj.data = response.data.rows;
}
...
angular.module("app").
controller("app.userManagementController", UserManagementController );
}

Related

How to wrapper multiple classes in different files into a single function in typescript

I am facing an issue with typescript build while trying to wrapper multiple classes into a single function.
Below is the sample code.
// AppState.ts
export class AppState {
static id: string;
}
// AppLogic.ts
import { AppState } from './AppState'
export class AppLogic{
constructor(id : string){
AppState.id = id;
}
public getAppID() : string{
return AppState.id;
}
}
// main.ts
import { AppLogic } from './AppLogic';
export function AppwrapAPI(id : string): any{
class AppAPI{
private app : AppLogic;
constructor(id : string){
this.app = new AppLogic(id);
}
public getAppID() : string{
return this.app.getAppID();
}
}
return new AppAPI(id);
}
<!DOCTYPE html>
<html>
<head>
<title>Test app</title>
</head>
<body>
<script type="module">
import { AppwrapAPI } from "./dist/main.es.js";
let a1 = new AppwrapAPI("123");
alert(a1.getAppID()); ///"123"
let a2 = new AppwrapAPI("321"); ///"321"
alert(a2.getAppID());
alert(a1.getAppID()); ///"321" <<--- wrong data
</script>
</body>
</html>
The above ts project generates the following js code using rollup built.
var AppState = /** #class */ (function () {
function AppState() {
}
return AppState;
}());var AppLogic = /** #class */ (function () {
function AppLogic(id) {
AppState.id = id;
}
AppLogic.prototype.getAppID = function () {
return AppState.id;
};
return AppLogic;
}());function AppwrapAPI(id) {
var AppAPI = /** #class */ (function () {
function AppAPI(id) {
this.app = new AppLogic(id);
}
AppAPI.prototype.getAppID = function () {
return this.app.getAppID();
};
return AppAPI;
}());
return new AppAPI(id);
}export{AppwrapAPI};//# sourceMappingURL=main.es.js.map
In this code, the AppwrapAPI function wraps only the AppAPI function instead of all the functions and the AppState function is outside the AppwrapAPI function which creates an issue when I create multiple instances for the AppwrapAPI function.
let a1 = new AppwrapAPI("123");
alert(a1.getAppID()); ///"123"
let a2 = new AppwrapAPI("321"); ///"321"
alert(a2.getAppID());
alert(a1.getAppID()); ///"321" <<--- wrong data
I want to wrapper all the three classes AppState, AppLogic, AppAPI inside the AppwrapAPI function so that the AppState is not shared between the multiple instances.
Similar to the below code
"use strict";
function AppwrapAPI(id) {
class AppState {
}
class AppLogic {
constructor(id) {
AppState.id = id;
}
getAppID() {
return AppState.id;
}
}
class AppAPI {
constructor(id) {
this.app = new AppLogic(id);
}
getAppID() {
return this.app.getAppID();
}
}
return new AppAPI(id);
}
let a1 = AppwrapAPI("123");
console.log(a1.getAppID()); /// output : 123
let a2 = AppwrapAPI("321");
console.log(a2.getAppID()); /// output : 321
console.log(a1.getAppID()); /// output : 123
Right now I manually modifying the generated code to avoid this issue but it gives me some other issue while debugging with the source map generated from the old file.
Can anyone suggest to me how to modify the typescript code to get the single function that wraps all the classes in the typescript project?

How do we mock private method using jasmine?

Trying to mock private method that is in the class could not get any success, I am using jasmine so in below code i have getDrug method that is making http call , Now i can mock core but how do i stub/mock getDrug so code coverage can be improve.
DrugPriceApi.node.ts
export class DrugPriceApi extends Types.ModuleBase < DrugPriceParam, DrugPriceResultSet[] > {
private _memberId: string = "";
private _dependencies: any;
private errorMessage: string = "There was an issue while retrieving drug price. Please try again.";
before(args: DrugPriceParam): Promise < DrugPriceParam > {
args.daysSupply = args.daysSupply ? args.daysSupply : args.appName === "VOYA" ? "90" : "BLNK";
return Promise.resolve(args);
}
core(args: DrugPriceParam, requestMethod: Interface.Core.RequestMethod, _dependencies: any): Promise < any > {
this._dependencies = _dependencies;
return new Promise < any > ((resolve: Function, reject: Function) => {
this.getDrug(function(resolve) {
resolve( //response here);});
}
}
}
}
}
private getDrug(args: DrugPriceParam, requestMethod: Interface.Core.RequestMethod) {
return requestMethod.http.makeRequest({
url: {
name: 'domain_getDrug',
params: {
version: '1.0',
appName: args.appName ? args.appName : 'WEB',
tokenId: args.tokenId,
refId: args.refId,
internalID: args.memberInfo.internalID,
searchText: args.drugName,
drugNdcId: 'BLNK'
}
},
body: {
memberInfo: args.memberInfo
}
});
}
DrugPriceApi.spec.ts
import {
DrugPriceApi
} from "./DrugPriceApi.node";
it("should get drugByName", function(done) {
let getDrug: any;
beforeEach((done) => {
function getMockData(url: string): Promise < any > {
const rtnval = {
"details": [],
"header": {
"statusDesc": "Success",
"statusCode": "0000",
"IndexOfRequestThatFailed": []
}
};
return Promise.resolve(rtnval);
}
let moderator: Interface.Mock.Handler = {
getMockData: getMockData
};
getDrug = moderator;
});
let param: any;
param.daysSupply = "BLNK";
param.quantity = "BLNK";
param.memberId = "1372";
const result: any = _sdkInstance.SDK.Pricing.getDrugPrice(param);
result.then(function(res: any) {
spyOn(DrugPriceApi.prototype, "core").and.callFake(() => {
expect(DrugPriceApi.prototype.getDrug).toHaveBeenCalled();
});
expect(res.Header.StatusCode).toBe("5000");
done();
});
});
I am a bit confused on what is happening here and why DrugPriceApi is being tested indirectly. It looks like we are testing Pricing.getDrugPrice instead of the DrugPriceApi.
If you want to test DrugPriceApi.core then you simple needs to create an instance of it and set DrugPriceApi.getDrug = jasmine.createSpy();
const api = new DrugPriceApi();
api.getDrug = jasmine.createSpy();
api.core(...whatever).then(() => {
expect(api.getDrug).toHaveBeenCalled();
});

Javascript ES6 MV(C) TypeError

I'm very new to JavaScript MVC logic. I'm trying to create a simple app.
I've set up everything like in the example (In seperate files ofc). Data.js which is not shown contains an object with some data, and template.js contains my html template strings.
// CONTROLLER
import Model from './models/model';
import View from './views/view';
import Controller from './controllers/controller';
import { $on } from './utility/utility';
export default class Controller {
constructor(Model, View) {
this.model = Model;
this.view = View;
};
loadInit() {
console.log("controller render");
this.model.test();
// this.view.render(this.model.data);
};
}
// MODEL
import data from '../config/data'
data.initialize();
export default class Model {
constructor() {
this.data = data;
};
test() {
console.log("Test works");
};
generateLists() {
window.infiniteList = [];
var articlesList = 'http://lib.lrytas.lt/api/articlesList/article.php?term=/lrytas/' + data.blockTag.slug + '/*&domain=' + data.blockTag.domain;
$.get(articlesList, function(response) {
for(let i = 0; i < response.blockTop7.length; i++) {
if (response.blockTop7[i].n18 == "0") {
window.infiniteList.push(response.blockTop7[i].main_id);
}
};
for(let i = 0; i < response.newBlock.length; i++) {
if (response.newBlock[i].n18 == "0") {
window.infiniteList.push(response.newBlock[i].main_id);
}
};
});
console.log(infiniteList);
};
loadArticle(data) {
$.get(lr_config.kolumbusApi + 'query/?kpm3id=' + infiniteList[0] + '&ret_fields=props', function(response) {
let result = response.result["0"].props;
this.data.update(result);
});
window.infiniteList.splice(0,1);
};
}
// VIEW
import config from '../config/config'
import Template from '../template/template'
import data from '../config/data'
data.initialize();
export default class View {
constructor() {
this.el = config.mainWrapper;
};
render(Data) {
console.log("view render");
this.el.innerHTML += Template(Data);
};
}
// APP.JS
class App {
constructor() {
this.model = new Model();
this.view = new View();
this.controller = new Controller(Model, View);
};
}
const app = new App();
const init = () => {
app.controller.loadInit();
}
$on(window, 'load', init);
Heres JSBIN.
Now the problem is when I'm trying to call init function on load in main.js. It goes to controller, calls the loadInit() function which then should call this.model.test(), but it wouldnt work and it gives me the following error
"Uncaught TypeError: this.model.test is not a function".
I've been trying to find a solution for past couple hours but I'm really lost here.
Any help would be greatly appreciated. Thanks!

Why $onInit method is not invoked in the example below?

I would like to use angular's component method, but it seems something is wrong. I have been double checking this code for a while. There is no typo, it seems it fits for the documentation, but, still, it is not working.
I have checked, Angular 1.5.3 is installed.
There is no output on the console. According to the documentation and this blog entry I should see the "onInit" text.
The component's template is displayed correctly, and I can see the the template is loaded, but it seems the controller is not instantiated / fired.
My app is written in Typescript.
The component:
module sayusiando.dilib.spa {
export class LeftHandMenuComponent implements ng.IComponentOptions {
public transclude: boolean = false;
public controller: Function = LeftHandMenuController;
public controllerAs: string = "vm";
public templateUrl: string = "app/layout/leftHandMenu/leftHandMenuTemplate.html";
}
angular
.module("dilib")
.component("dilibLeftHandMenu", new LeftHandMenuComponent());
}
compiled code:
var sayusiando;
(function (sayusiando) {
var dilib;
(function (dilib) {
var spa;
(function (spa) {
var LeftHandMenuComponent = (function () {
function LeftHandMenuComponent() {
this.transclude = false;
this.controller = spa.LeftHandMenuController;
this.controllerAs = "vm";
this.templateUrl = "app/layout/leftHandMenu/leftHandMenuTemplate.html";
}
return LeftHandMenuComponent;
})();
spa.LeftHandMenuComponent = LeftHandMenuComponent;
angular
.module("dilib")
.component("dilibLeftHandMenu", new LeftHandMenuComponent());
})(spa = dilib.spa || (dilib.spa = {}));
})(dilib = sayusiando.dilib || (sayusiando.dilib = {}));
})(sayusiando || (sayusiando = {}));
Layout template:
<div>
<dilib-left-hand-menu class="col-lg-2"></dilib-left-hand-menu>
</div>
LeftHandMenuController:
module sayusiando.dilib.spa {
"use strict";
export interface ILeftHandMenuController {
}
export class LeftHandMenuController implements ILeftHandMenuController {
$onInit: Function = (() => {console.log("onInit");});
static $inject = ["LeftHandMenuService"];
constructor(leftHandMenuService: sayusiando.dilib.spa.ILeftHandMenuService) {
console.log("con");
this.leftHandMenuService = leftHandMenuService;
//this.activate();
console.log("construct");
}
activate() { //activate logic }
}
angular
.module('dilib')
.controller('leftHandMenuController', LeftHandMenuController);
}
Compiled controller code:
var sayusiando;
(function (sayusiando) {
var dilib;
(function (dilib) {
var spa;
(function (spa) {
"use strict";
var LeftHandMenuController = (function () {
function LeftHandMenuController(leftHandMenuService) {
this.$onInit = (function () { console.log("onInit"); });
console.log("con");
this.leftHandMenuService = leftHandMenuService;
//this.activate();
console.log("construct");
}
LeftHandMenuController.prototype.activate = function () {
var _this = this;
this.leftHandMenuService.getLeftHandMenu()
.then(function (result) {
_this.leftHandMenu = result;
});
};
LeftHandMenuController.$inject = ["LeftHandMenuService"];
return LeftHandMenuController;
})();
spa.LeftHandMenuController = LeftHandMenuController;
angular
.module('dilib')
.controller('leftHandMenuController', LeftHandMenuController);
})(spa = dilib.spa || (dilib.spa = {}));
})(dilib = sayusiando.dilib || (sayusiando.dilib = {}));
})(sayusiando || (sayusiando = {}));
I called the $oninit in a wrong way. Here is the proper, well working code:
module sayusiando.dilib.spa {
"use strict";
export interface ILeftHandMenuControllerScope {
}
export class LeftHandMenuController implements ILeftHandMenuControllerScope {
public leftHandMenu: Array<sayusiando.dilib.spa.IModuleContract>;
static $inject = ["leftHandMenuService"];
constructor(
private leftHandMenuService: sayusiando.dilib.spa.ILeftHandMenuService) {
}
public $onInit = () => {
this.leftHandMenuService.getLeftHandMenu()
.then((result: Array<sayusiando.dilib.spa.IModuleContract>): void => {
this.leftHandMenu = result;
});
}
}
angular
.module('dilib')
.controller('leftHandMenuController', LeftHandMenuController);
}
I think this is due to missing dependency parameter list on the module definition. There is a difference in these two statements:
angular.module("dilib")
angular.module("dilib",[])
The first statement tries to access an existing module with name dilib, whereas the second statement tries to create a module dilib with no dependencies. I believe you are trying to create a new module, and hence will need the second format.

Typescript - Problems with the lexical scoping => this

My Problem is with the following function:
() => this.handleRes(res, this.lobbyInitFn(this.$log, this.lobbyData))
What is the best way to get a reference to my lobbyData variable on the Ctrl?
As a result of the fat arrow syntax I get a pointer to the global window object.
At the moment I just get a reference to $log function in the lobbyInitFn method and an undefined for the dataCol parameter.
module lobby.controllers {
'use strict';
class LobbyCtrl{
public lobbyData : Array<string>;
constructor(private $scope, private $log : ng.ILogService, private lobbyStorage) {
this.init();
}
private init(){
this.initializeLobbyData();
}
private initializeLobbyData(){
var res = this.lobbyStorage.LobbyRoom().query(
() => this.handleRes(res, this.lobbyInitFn(this.$log, this.lobbyData)),
() => this.handleErr("Error while initializing the lobby data."));
}
private lobbyInitFn(logger, dataCol){
return function(data){
for (var i = 0; i < data.length; ++i) {
logger.log(data[i]);
}
dataCol = data;
}
}
// Common functions => outsourcing
private handleRes(res : any, resFn? : callbackFn) {
if(typeof resFn != 'undefined') {
resFn(res)
} else{
this.$log.log(res);
}
}
private handleErr(err : string, errFn? : callbackFn) {
if(typeof errFn != 'undefined') {
errFn(err)
} else{
this.$log.error(err);
}
}
}
Can you try:
() => this.handleRes(res, () => this.lobbyInitFn(this.$log, this.lobbyData))

Categories

Resources