Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class Member becomes undefined

I am quite new to TypeScript and I experience a strange problem at the moment. I create an instance of my main class when the document is ready, using JQuery.

var main: MainApp;
$(document).ready(function () {
   main = new MainApp();
});

The simplified MainApp Class:

class MainApp {
   // Helper Objects
   net: AppNetworking;
   urlHelper: UrlHelper;
   cat: Category;

   // Construction
   constructor() {
      this.net = new AppNetworking();
      this.urlHelper = new UrlHelper();
   }

   // Ajax Callback with Data needed to initialize the "cat" object
   private AjaxCallback(categoryData){
      this.cat = new Category(categoryData);
   }

   // Event Handler for an HTML-Element
   // As it would be called anonymously in JS I decided to make it a static function
   static onClickSendButton(): void{
      // Using some members of the MainApp
      var hostUrl: string = main.urlHelper.getQueryStringParam("HostUrl");

      if (main.cat.isValidCategory()) {
         main.sendCategory();
      }
   }

   sendCategory(): boolean {
      // Some logic to send data via AJAX
   }
}

The function is being registered to the onClick Event of a Button on construction of the MainApp Class.

$("#btnSendCat").click(MainApp.onClickSendButton);

When the function onClickSendButton() gets called, it produces the error:

Uncaught TypeError: Cannot read property 'isValidCategory' of undefined

When debugging, the urlHelper Instance is defined, but the cat Instance is undefined. As I do not touch the instance cat anywhere in my application, I'm really confused how it is undefined. Also when checking the main variable all members are defined!

Am I doing anything illegal here? Could there be issues with that code?

like image 648
Vinz Avatar asked Dec 10 '14 11:12

Vinz


2 Answers

Completely revised answer. I actually answered with the two most common scenarios for this error, but actually your problem is different.

The usual answers are

  1. Make sure you are referencing .js files, not .ts files
  2. Make sure you are loading scripts in the correct order

In your case, this is not the problem and your code is sufficient to recreate the issue.

I have put together the following test, filling in the blanks - and it works as expected.

app.ts

declare var main: MainApp;

class AppNetworking {

}

class UrlHelper {
    getQueryStringParam(input: string) {
        console.log('Got here getQueryStringParam');
        return input;
    }
}

class Category {
    isValidCategory() {
        console.log('Got here isValidCategory');
        return true;
    }
}

class MainApp {
   // Helper Objects
   net: AppNetworking;
   urlHelper: UrlHelper;
   cat: Category;

   // Construction
   constructor() {
      this.net = new AppNetworking();
      this.cat = new Category();
      this.urlHelper = new UrlHelper();
   }

   // Event Handler for an HTML-Element
   // As it would be called anonymously in JS I decided to make it a static function
   static onClickSendButton(): void{
      // Using some members of the MainApp
      var hostUrl: string = main.urlHelper.getQueryStringParam("HostUrl");

      if (main.cat.isValidCategory()) {
         main.sendCategory();
      }
   }

   sendCategory(): boolean {
       // Some logic to send data via AJAX
       return true;
   }
}

index.html snip

<div id="btnSendCat">BTN SEND CAT</div>
<script src="app.js"></script>
<script src="Scripts/jquery-2.1.1.min.js"></script>
<script>
    var main;
    $(document).ready(function () {
        main = new MainApp();
        $("#btnSendCat").click(MainApp.onClickSendButton);
    });
</script>

The result of running this test is the following output in the console window:

"Got here getQueryStringParam" app.js:10
"Got here isValidCategory" app.js:19
like image 104
Fenton Avatar answered Nov 15 '22 08:11

Fenton


I left some important parts of my App out, I'm sorry. Later in the project I used to reinitialize that Category Object. This re initialization was done in an AJAX-Callback Function. This function runs outside of my Object and this wont be my MainApp Class but the Window. I think it's what you call an anonymous function in JavaScript.

I fixed that issue by taking use of my global main Variable

class MainApp {
   // Called anonymous so it should be a static function
   private AjaxCallback(categoryData){
      // this.cat = new Category(categoryData);  ! this will be the Window Instance and not a MainApp Instance

      main.cat = new Category(categoryData); // Initialization using the "main" variable
   }
}

The call in my onClickSendButton Method to this.cat succeeds now, as this.cat was reinitialized correctly.

This video helped me a lot in my researches: Understanding "this" in TypeScript

like image 45
Vinz Avatar answered Nov 15 '22 09:11

Vinz