0

I have a problem catching my object data in jQuery methods:

this.start = function() {
            var prepend = '<img id = "' + this.imageList[0].name + '" class = "desktop_image_slider_prepended_image" src = "res/img/' + this.imageList[0].name + '.png"></img>';
            $("#desktop_image_slider").prepend(prepend);
            this.boxList.shift(this.imageList[0]);
            $("#" + this.boxList[this.boxList.length-1].name).animate({"width":"0%"}, 500);
            $("#" + this.imageList[0].name).animate({"width":"11.1111111111%"}, 500, function() {
                $("#" + this.boxList[this.boxList.length-1].name).remove();
                this.imageList.push(this.boxList[this.boxList.length-1]);
                this.boxList.splice(this.boxList.length-1, 1);
                $timeout(function() {
                    this.start();
                }, 1000);
            });
        }

It throws undefined. It is obviously taking something from jQuery not from my method. Is there a way to access my method?

Thanks!

4
  • 1
    The this referenced in your animate function event handler is referencing the calling event function. Not your global this. You can either use .bind(this) or use const _self = this; and then reference _self.imageList. Commented Jun 14, 2017 at 19:36
  • use @VtoCorleone reply as it is the proper way to use this in Jquery Commented Jun 14, 2017 at 19:40
  • Yes that the best way and I was able to make it work with Your comment, You were the first to answer You should post an answer so I can vote it if You would like. Commented Jun 14, 2017 at 19:54
  • Just posted an answer for the street cred. Glad this worked @EnvironmentGenerator Commented Jun 14, 2017 at 20:09

5 Answers 5

2

try to pass the object this as a parameter in the function.

Sign up to request clarification or add additional context in comments.

Comments

1

The this referenced in your animate function event handler is referencing the calling event function. Not your global this. You can either use .bind(this) or use const _self = this; and then reference _self.imageList

This example uses const _self = this.

start = function() {
    var prepend = '<img id = "' + this.imageList[0].name + '" class = "desktop_image_slider_prepended_image" src = "res/img/' + this.imageList[0].name + '.png"></img>';
    $("#desktop_image_slider").prepend(prepend);
    this.boxList.shift(this.imageList[0]);
    $("#" + this.boxList[this.boxList.length-1].name).animate({"width":"0%"}, 500);
    var _self = this;
    $("#" + this.imageList[0].name).animate({"width":"11.1111111111%"}, 500, function() {
        $("#" + _self[_self.boxList.length-1].name).remove(); // _self is used instead of this
        _self.imageList.push(_self.boxList[_self.boxList.length-1]); // _self is used instead of this
        _self.boxList.splice(_self.boxList.length-1, 1); // _self is used instead of this
        $timeout(function() {
            _self.start(); // _self is used instead of this
        }, 1000);
    });
}

This example uses bind

this.start = function() {
    var prepend = '<img id = "' + this.imageList[0].name + '" class = "desktop_image_slider_prepended_image" src = "res/img/' + this.imageList[0].name + '.png"></img>';
    $("#desktop_image_slider").prepend(prepend);
    this.boxList.shift(this.imageList[0]);
    $("#" + this.boxList[this.boxList.length-1].name).animate({"width":"0%"}, 500);
    $("#" + this.imageList[0].name).animate({"width":"11.1111111111%"}, 500, function() {
        $("#" + this.boxList[this.boxList.length-1].name).remove();
        this.imageList.push(this.boxList[this.boxList.length-1]);
        this.boxList.splice(this.boxList.length-1, 1);
        $timeout(function() {
            this.start();
        }.bind(this), 1000); // set function's scope to `this`
    }.bind(this)); // set function's scope to `this`

Comments

1

When you go into another function context, this will be different. Therefore, store this in another variable first

start = function() {
            var prepend = '<img id = "' + this.imageList[0].name + '" class = "desktop_image_slider_prepended_image" src = "res/img/' + this.imageList[0].name + '.png"></img>';
            $("#desktop_image_slider").prepend(prepend);
            this.boxList.shift(this.imageList[0]);
            $("#" + this.boxList[this.boxList.length-1].name).animate({"width":"0%"}, 500);
            var oldThis = this;
            $("#" + this.imageList[0].name).animate({"width":"11.1111111111%"}, 500, function() {
                $("#" + oldThis.boxList[this.boxList.length-1].name).remove();
                oldThis.imageList.push(this.boxList[this.boxList.length-1]);
                oldThis.boxList.splice(this.boxList.length-1, 1);
                $timeout(function() {
                    oldThis.start();
                }, 1000);
            });
        }

Comments

1

Any time you define an anonymous function to be called at a later time you will lose your expected this. One way to fix it is to use bind, for example:

this.start = function() {
    var prepend = '<img id = "' + this.imageList[0].name + '" class = "desktop_image_slider_prepended_image" src = "res/img/' + this.imageList[0].name + '.png"></img>';
    $("#desktop_image_slider").prepend(prepend);
    this.boxList.shift(this.imageList[0]);
    $("#" + this.boxList[this.boxList.length-1].name).animate({"width":"0%"}, 500);
    $("#" + this.imageList[0].name).animate({"width":"11.1111111111%"}, 500, function() {
        $("#" + this.boxList[this.boxList.length-1].name).remove();
        this.imageList.push(this.boxList[this.boxList.length-1]);
        this.boxList.splice(this.boxList.length-1, 1);
        $timeout(function() {
            this.start();
        }.bind(this), 1000); // bind this to timeout callback
    }.bind(this)); // bind this to animate callback
}

Comments

1

Use the arrow function to maintain the same this for the anonymous function lexical context:

$("#" + this.imageList[0].name).animate({"width":"11.1111111111%"}, 500, () => {
  ... with this
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.