0

I'm trying to make some jQuery functions a little easier to implement and so I tried to encapsulate some autocomplete logic into a function to allow a user to send in a variable of the URL, the parameter of the web service and the control whose value we need to take. With the following script I get the error: response is not defined. The idea is that in this web service there will be many different methods which have autocomplete functionality and I can simply pass the name of the appropriate method and its parameter to the Complete method and have the functionality on multiple text boxes.
Why is it that

 $(document).ready(function ()
        {

            $('#auto').autocomplete(
            {

                source: function (request, response)
                {
                    Complete('GetNames', 'hospitalName', '#auto');
                }
            });
            function Complete(url, varName, target)
            {
                $.ajax(
                    {

                        type: "POST",
                        url: "Service.asmx/" + url,
                        data: "{'" + varName + "':'" + $(target).val() + "'}",
                        dataType: "json",
                        contentType: "application/json",
                        success: function (data)
                        {
                            //uncaught reference error response is not defined
                            response(data.d);
                        },
                        error: function (xhr)
                        {
                            console.log(xhr.status);
                        }
                    });
            }

        });

This was working fine before I tried to take out the AJAX call and make it its own method. I'd like to know

  1. the source function is calling the Complete function and the source function has request and response as parameters, so why are they undefined in my script?
  2. how can I fix this and avoid future problems in #1.
4
  • The scope of parameters is the just that function body. Since Complete is not within the body of the source: function, response is out of scope. Commented Oct 1, 2013 at 17:14
  • So it doesn't matter then that Complete is called within the scope of source? Hm.. more reading to do. Thanks for the insight. Commented Oct 1, 2013 at 17:17
  • You need to understand the difference between lexical scope and dynamic scope. JS uses lexical scoping, which means the scope refers to the textual body of the function. Commented Oct 1, 2013 at 17:25
  • @Barmar yep. Now that I know what the name is, I know what to look for. :) Commented Oct 1, 2013 at 17:26

2 Answers 2

2

Previously it was working because the variable response was available in the closure scope of the ajax success callback method. Since you created a separate method now the ajax callback is not within the closure scope of the source method so you need to pass the request and response parameters as arguments to the Complete method

$(document).ready(function () {

    $('#auto').autocomplete({
        source: function (request, response) {
            Complete(request, response, 'GetNames', 'hospitalName', '#auto');
        }
    });

    function Complete(request, response, url, varName, target) {
        $.ajax({

            type: "POST",
            url: "Service.asmx/" + url,
            data: "{'" + varName + "':'" + $(target).val() + "'}",
            dataType: "json",
            contentType: "application/json",
            success: function (data) {
                //uncaught reference error response is not defined
                response(data.d);
            },
            error: function (xhr) {
                console.log(xhr.status);
            }
        });
    }

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

2 Comments

I know a tiny bit about closures (I think). From what I understand a closure allows you to get a variables value outside of the scope of a function. Is this correct?
@wootscootinboogie not outside the scope of the function, a variable declared in a function will be available in functions which is defined within the outer function. Read more in this and this
1

You can do it by passing the values to Complete, as in Arun P Johny's answer. You can also make Complete a closure within the source: function:

$(document).ready(function () {
    $('#auto').autocomplete({
        source: function (request, response) {
            Complete('GetNames', 'hospitalName', '#auto');
            function Complete(url, varName, target) {
                var data = [];
                data[varname] = $(target).val();
                $.ajax({

                    type: "POST",
                    url: "Service.asmx/" + url,
                    data: JSON.stringify(data),
                    dataType: "json",
                    contentType: "application/json",
                    success: function (data) {
                        response(data.d);
                    },
                    error: function (xhr) {
                        console.log(xhr.status);
                    }
                });
            }
        }
    });
});

Since it's nested within that function, it has access to its local variables.

However, if the reason you pulled the AJAX code outside the source: option in the first place was because you wanted to be able to call it from other places (so you can pass different URLs, targets, or variable names), this won't work -- the function is only accessible from within that function.

P.S. Don't try to construct your own JSON that way, use JSON.stringify() as I showed.

1 Comment

You are correct, the reason why I tried to isolate the AJAX call was to make it easier to call from other places. I envisioned something like control.Complete(parameters). I'm glad I asked instead of trying to do something that was impossible for half the afternoon. Gratzie.

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.