How to access to $(this) when bind(this) is used?

Rockj Source

Suppose I have a form attached to the following javascript function:

$('#foo').submit(function (event)
{
    event.preventDefault();

    if (!this.validate()) {
        return;
    }

    console.log($(this).attr('action'));
}.bind(this));

now the main problem is that the submit function attached to #foo is available inside a class which contains other functions, eg: validate:

Helper.prototype.validate = function()
{
    // some content
}

I need to access to those functions using this, so I attached at the end of the submit the code: bind(this) and I'm able to invoke the validate function of Helper class simply using this.validate.

The scenario above will cause some issue on the $(this) parameter, infact if I try to access to the action of the form, then I'll get an empty string because javascript will search the variable action inside the class Helper.

If I remove bind(this) I can access to the action of the form, but I'll lose the access to validate function.

Someone have an idea to fix this?

The generic structure of the js file is this:

function()
{
    Helper.prototype.bindEventHandlers = function()
    {
        $('#foo').submit(function (event)
        {
            event.preventDefault();

            if (!this.validate()) {
                return;
            }

            console.log($(this).attr('action'));
        }.bind(this));

        Helper.prototype.validate = function()
        {
           ...
        });
    }
}
javascriptjquery

Answers

answered 6 days ago Quentin #1

You can't.

The entire point of bind is that you replace the value of this.

If you want to have access to this and another value, then don't use bind. Store the value in a different variable. Consider an IIFE instead:

$('#foo').submit(
  function (context) {
    return function(event) {
      event.preventDefault();

      if (!context.validate()) {
        return;
      }

      console.log($(this).attr('action'));
    }
  }(this)
);

You might want to split it up to make it less unwieldy:

function thingy_factory(context) {
  function thingy(event) {
    event.preventDefault();
    if (!context.validate()) {
      return;
    }

    console.log($(this).attr('action'));
  }
  return thingy;
}

and

$('#foo').submit(thingy_factory(this));

answered 6 days ago aaronofleonard #2

I would say instead of relying on the keyword this, just set up a reference to the current value of this outside of the jQuery callback.

function(){
   Helper.prototype.bindEventHandlers = function(){
       var context = this;
       $('#foo').submit(function (event){
            event.preventDefault();

            if(!context.validate()){
                return;
            }

            console.log($(this).attr('action'));
        });

    }

     Helper.prototype.validate = function(){
         ...
     });
}

I moved Helper.prototype.validate out of the the bindEventHandlers, I'm assuming that's what your intention is. Might have just been a formatting error.

answered 6 days ago Ciprian B #3

Before of $('#foo').submit you can add var that = this; and validate function will be called in this way: that.validate()

comments powered by Disqus