Samantha J T Star
Samantha J T Star

Reputation: 32758

How can I pass a class variable into a function inside a function with typescript?

I created a Modal class like this:

export class Modal {
        link: Link;
        constructor (link: Link) {
            this.link = link;
        }
        create() {
            this.link.Modal.$Modal = $.modal({ });
        }
        addSubmit() {
            this.link.Modal.$Form.submit(function () {
                var a = this.link;
                submitHandler(this.link);
                return false;
            });
        }
}

Here is the code that I am using:

var modal = new Modal(link);
modal.create();
modal.addSubmit();

There is a problem here. I want to pass the link as a parameter to the submitHandler function. However it seems it's not there. Also when I check everthing on the line "var a = this.link" it seems that the variable "a", the "this" and the "link" all show as "any" when I hover over them.

Upvotes: 1

Views: 919

Answers (1)

Fenton
Fenton

Reputation: 250872

You have discovered JavaScript scope - which can be confusing at first.

JavaScript is functionally scoped. This means that the variables belong to the function they are declared in.

When the variable is declared outside the function, JavaScript attempts to walk up the chain to find the variable.

This is confusing when the context you type the code in is not the context your code is called in. In your case, this in the context of the submit function is the element that is being submitted (a form element for example). It isn't the class where you write the submit function.

Here is an update that should work:

export class Modal {
    link: Link;
    constructor (link: Link) {
        this.link = link;
        this.link.Modal.$Modal = $.modal({ });
    }

    addSubmit() {
        var _this = this;
        this.link.Modal.$Form.submit(function () {
            var a = _this.link;
            submitHandler(_this.link);
            return false;
        });
    }
}

In this example we put this into a variable with a name that won't be overridden so the JavaScript runtime won't stop looking until it finds it. (It will stop looking for this straight away as it will have it defined locally as the form element). As there is no local _this JavaScript will walk up the chain until it discovers our variable, which represents the class.

There is also a short-hand in TypeScript to do this, which results in the same JavaScript as we have hand-written above:

export class Modal {
    constructor (public link: Link) {
        this.link.Modal.$Modal = $.modal({ });
    }

    addSubmit() {
        this.link.Modal.$Form.submit(() => {
            var a = this.link;
            submitHandler(this.link);
            return false;
        });
    }
}

Lastly, you don't want calling code to have to rely on calling functions in a specific order for things to work. This is an example of exposing the internal workings of your class, so I have updated the usage of the class to be:

var modal = new Modal(link);
modal.addSubmit();

I am assuming that addSubmit is optional - otherwise the Modal class should do that too without the calling code having to know about it.

Upvotes: 5

Related Questions