1

I am getting a list from C# web method with ajax (code below), the list is returned fine, but after the success method is done, it gives me an error - (Cannot read property 'length' of undefined) in the jquery (screenshot below)

Am I missing something ??

function getMainParentMenus() {

    $.ajax({
        type: "POST",
        url: "/Mainpage.aspx/getLeftMainNavParentMenus",

        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (msg) {
            alert(msg.d);
            parentMenuss = msg.d;
        }, //It goes to the screenshot below after this bracket
        error: function (error) {
            alert("An error has occured while fetching the Left Nav Parent Menus");
        }
    });

};

enter image description here

The method above is called by the below method.

    var parentMenuss;
    var listOfSubMenus;
    function bindLeftNavMenu() {
//    var parentMenus = getMainParentMenus();


getMainParentMenus();



    var html = "<div id='accordian'> ddd";

    $.each(parentMenuss, function () {

        html += " <h3 class='accordianHeader' href='" + this['URL'] + "'>" + this['Title'] + "</h3>  ";
        alert("okK");
        $.each(listOfSubMenus, function () {
            html += "<div class='accordianContent'><a href='" + this['URL']  + "'>" + this['Title'] + "</a>";
        });

    });
    html += "</div>";
    $("#leftNavigationMenu").append(html);
 };

EDIT :

the data in the alert in the first block of code above is displayed like so enter image description here

and in the chrome debugger : enter image description here

dcodesmith
  • 9,590
  • 4
  • 36
  • 40
drinu16
  • 775
  • 2
  • 11
  • 25
  • It looks like you are having an asynchronous issue (i,e, `parentMenuss` isn't defined when `$.each` is called), what does the data look like that is returned from the ajax call? – fbynite Dec 20 '13 at 19:51
  • Or said another way: `parentMenuss` is *not set* until after the XHR success callback runs. Make sure the code that uses `parentMenuss` is executed *after* (i.e. from within or response to) the XHR success callback. – user2864740 Dec 20 '13 at 19:53
  • `parentMenuss === undefined` and `$.each(undefined,function(){...})` isn't going to work. – Kevin B Dec 20 '13 at 19:56
  • question edited with how the data is displayed – drinu16 Dec 20 '13 at 19:57
  • 1
    Well, using alert() in debugging purpose is generally not agreat idea, use your console with console.log() e.g. BTW, your issue is quite simple, you cannot return value from async request, see duplicate topic for how to use ajax result – A. Wolff Dec 20 '13 at 19:59

2 Answers2

1

Because getMainParentMenus is using AJAX it is asynchronous. Your next line of code after calling getMainParentMenus will be executed before the .success part of your AJAX call, so it will be executed before parentMenuss has been populated.

There are a few ways you can tackle this, one way would be to pass the callback function to getMainParentMenus, something like this:

function getMainParentMenus(myCallback) {
    $.ajax({
        type: "POST",
        url: "/Mainpage.aspx/getLeftMainNavParentMenus",

        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (msg) {
            alert(msg.d);
            parentMenuss = msg.d;
            if (callback && typeof(callback)==="function") {
                callback();
            }
        }, //It goes to the screenshot below after this bracket
        error: function (error) {
            alert("An error has occured while fetching the Left Nav Parent Menus");
        }
    });

};

Now you can call it like this:

var html = "<div id='accordian'> ddd";

getMainParentMenus(function() { 
    $.each(parentMenuss, function () {
        html += " <h3 class='accordianHeader' href='" + this['URL'] + "'>" + this['Title'] + "</h3>  ";
        alert("okK");
        $.each(listOfSubMenus, function () {
            html += "<div class='accordianContent'><a href='" + this['URL']  + "'>" + this['Title'] + "</a>";
        });
    });
});
Matt Burland
  • 44,552
  • 18
  • 99
  • 171
0

Your code for rendering the menus is being executed immediately after getMainParentMenus(); Javascript does not wait for the ajax call to complete before moving on to the next block. It is operating asynchronously, as others have mentioned in the comments.

Your code has to wait for the ajax call to complete before trying to display the data.

jQuery supports deferred execution and promises, so you can create code that will not execute until other code has completed. This is the preferred way of handling asynchronous operations.

Try this:

function getMainParentMenus() {
    var request = $.ajax({
        type: "POST",
        url: "/Mainpage.aspx/getLeftMainNavParentMenus",

        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    }, //It goes to the screenshot below after this bracket
        error: function (error) {
            alert("An error has occured while fetching the Left Nav Parent Menus");
        }
    });
    return request;
}


var parentMenuss;
var listOfSubMenus;
function bindLeftNavMenu() {

    getMainParentMenus().success(function (result) {
        var html = "<div id='accordian'> ddd";

        $.each(parentMenuss, function () {
            html += " <h3 class='accordianHeader' href='" + this['URL'] + "'>" + this['Title'] + "</h3>  ";
            alert("okK");
            $.each(listOfSubMenus, function () {
                html += "<div class='accordianContent'><a href='" + this['URL']  + "'>" + this['Title'] + "</a>";
            });
        });
        html += "</div>";
        $("#leftNavigationMenu").append(html);
    });
}
Nick Zimmerman
  • 1,471
  • 11
  • 11