Home > Software engineering >  How to Self Reference an Object when "this" Refers to Something Else
How to Self Reference an Object when "this" Refers to Something Else

Time:10-08

I'm trying to create a modular series of element handlers for an app that has pages with varieties of configurations (eg: 'Hex T' config has elements 'A' thru 'O' that each has at least 1 DOM element that can be modified in different ways, but 'Square Pad' only has 'A' thru 'E' and the same lettered elements don't always refer to the same type of element, be it a dropdown or number input).

So what I've done is made classes like LengthElement that has 2 number inputs, one for Feet and one for Inches, and so LengthElement holds the value in inches, and then whenever one of the elements, Feet or Inches, gets updated, it registers that change to the inches value and then changes the Feet and Inches elements to properly display the correct measurement (eg: 10ft 0in => 10ft -1in => 9ft 11in).

There's also a config array that holds the list of all the various configurations the app can have, and what order the elements are in and what they are. I ID active inputs as 'input' and disabled inputs as 'box', it just helps me keep things straight. So, a Hex T active input pair for 'A' would have elements foot: '#ht-a-ft-input' and inch: '#ht-a-in-input'. I did this so I don't have to write out all the IDs for every single possible element (there are currently over 100 on just this page) more than once.

There's also an app requirement where certain lengths have to be divisible by 7, and I've got the logic in here. It's probably not relevant but I figured that I'd include it as it is just in case. Finally, there's an OnChange() function that gets passed into each object instance, that's a function with a callback that appears elsewhere that's working just fine so I don't think it matters.

Here's the class code in its entirety:

class LengthElement {
    inches;     //Value of the Two Elements in Inches
    foot;       //String of the Foot Element
    inch;       //String of the Inch Element
    div7;       //Flag to determine if change needs to be Divisible by 7
    OnChange;   //Function specific to the instance to be called whenever the input changes

    constructor(i, cfg, abrv, oC) {
        this.inches = i;

        if (cfg.foot == 'input') {
            this.foot = '#'   abrv   '-'   cfg.name   '-ft-input';
            $(this.foot).on('input', this.InputVal);
        }
        else {
            this.foot = '#'   abrv   '-'   cfg.name   '-ft-box';
        }
        if (cfg.inch == 'input') {
            this.inch = '#'   abrv   '-'   cfg.name   '-in-input';
            $(this.inch).on('input', this.InputVal);
        }
        else {
            this.inch = '#'   abrv   '-'   cfg.name   '-in-box';
        }

        this.div7 = cfg.div7;
        this.OnChange = oC;
    }

    GetFeet(i) {
        return Math.floor(i / 12);
    }

    GetInches(i) {
        return i % 12;
    }

    GetDiv7(i) {
        if (i % 7 > 5) {
            return i   (7 - (i % 7));
        }
        else {
            return i - (i % 7);
        }
    }

    GetVal() {
        return this.inches;
    }

    UpdateVal(i) {
        if (this.div7) {
            this.inches = this.GetDiv7(i);
        }
        else {
            this.inches = i;
        }

        $(this.foot).val(this.GetFeet(this.inches));
        $(this.inch).val(this.GetInches(this.inches));
    }

    InputVal() {
        var newInches = ($(this.foot).val() * 12)   $(this.inch).val();
        var change = newInches - this.inches;

        if (this.div7) {
            if (change > 0) {
                newInches = this.inches   ((Math.floor(change / 7) * 7)   7);
            }
            else if (change < 0) {
                newInches = this.inches - ((Math.floor(change / 7) * 7)   7);
            }
            else {
                newInches = this.GetDiv7(newInches);
            }
        }

        this.UpdateVal(newInches);
        this.OnChange();
    }
}

So what's the problem?

Whenever InputVal() gets called, this refers to a jQuery object, and not the object it's inside of. I believe the critical lines are the $(this.foot).on('input', this.InputVal); lines, but I'm not sure what exactly is wrong with them.

Again, this is to avoid writing out every single element's ID more than the one time where it's declared in the HTML, so any alternatives that I can use to perform the same task are appreciated.

I am about 4 months into solo development so I can't change frameworks off of jQuery. I would have an aneurysm.

CodePudding user response:

you could try inserting this at the top of your constructor

this.InputVal = this.InputVal.bind(this)

so that this inside of the InputVal function always refers to LengthElement

CodePudding user response:

the simple trick for that you should declare a variable name self, in constructor you binding self = this, in other method or callback you can using self instead of this

  • Related