Robert
Robert

Reputation: 10390

jQuery passing arguments to callback not working on .keyup()

I made a simple autocomplete feature as follows:

$(document).ready(function(){   
    $('#search-field').keyup(function(e) {
        ajaxAutocomplete(e);
    });
});


function ajaxAutocomplete(e) {
    var hash_tag = $.trim($(this).val());

    $.ajax({
        url     : 'autocomplete.php',
        method  : 'GET',
        dataType: 'html',
        data    : {tag : hash_tag}
    })
    .done(function(response) {
        if (response) {
            $('.datalistPlaceholder').html(response).show();
        } else {
            $('.datalistPlaceholder').hide();
        }
    })
    .fail(function() {
        alert('Something went wrong');
    });
}

I am trying to use the event object in ajaxAutocomplete function as described by jQuery: https://learn.jquery.com/about-jquery/how-jquery-works/

The above set up does not work and returns this: jquery.js:7328 Uncaught TypeError: Cannot read property 'toLowerCase' of undefined

This does work after removing the callback from above:

$(document).ready(function(){   
    $('#search-field').keyup(ajaxAutocomplete);
});

function ajaxAutocomplete() {
    var hash_tag = $.trim($(this).val());

    $.ajax({
        url     : 'autocomplete.php',
        method  : 'GET',
        dataType: 'html',
        data    : {tag : hash_tag}
    })
    .done(function(response) {
        if (response) {
            $('.datalistPlaceholder').html(response).show();
        } else {
            $('.datalistPlaceholder').hide();
        }
    })
    .fail(function() {
        alert('Something went wrong');
    });
}

Upvotes: 0

Views: 85

Answers (3)

Rory McCrossan
Rory McCrossan

Reputation: 337626

The problem with your first example is because you wrap the call to ajaxAutocomplete() in an anonymous function which means that you lose the reference of this within your called function (it will point to the window instead of the #search-field element). This in turn means that $(this).val() returns nothing - hence the error coming from jQuery.

You need to either use .call(this) when calling your function to maintain the scope of this within the function:

$(document).ready(function(){   
    $('#search-field').keyup(function(e) {
        ajaxAutocomplete.call(this);
    });
});

Working example

Alternatively you can use your second method which passes the ajaxAutocomplete function reference to the event handler which then maintains scope:

$(document).ready(function(){   
    $('#search-field').keyup(ajaxAutocomplete);
});

Personally I prefer the latter approach for its brevity.

Upvotes: 0

Robert
Robert

Reputation: 10390

After combining Rory's answer above and reading about .call() from MDN I came up with the following that works:

$(document).ready(function(){   
    $('#search-field').keyup(function(e) {
        ajaxAutocomplete.call(this, e);
    });
});

function ajaxAutocomplete(e) {
    console.log(e)
    var hash_tag = $.trim($(this).val());

    $.ajax({
        url     : 'autocomplete.php',
        method  : 'GET',
        dataType: 'html',
        data    : {tag : hash_tag}
    })
    .done(function(response) {
        if (response) {
            $('.datalistPlaceholder').html(response).show();
        } else {
            $('.datalistPlaceholder').hide();
        }
    })
    .fail(function() {
        alert('Something went wrong');
    });
}

Result on typing 'a':

j…y.Event {originalEvent: KeyboardEvent, type: "keyup", timeStamp: 1292.2500000000002, jQuery21406902543265129839: true, keyCode: 65…}

Upvotes: 1

JSchirrmacher
JSchirrmacher

Reputation: 3362

When calling a function, the context this gets lost. If you use the callback directly, the context is available.

Upvotes: 0

Related Questions