Search code examples
javascriptjqueryweb-servicesgetjsonwebservice-client

Nested JQuery Function Returns 'undefined' or '[object Object]'


Hello Friends on StackOverflow:

I am struggling to find what is causing a nested jQuery function to return values of 'undefined' or '[object Object]'. I have commented the location of the first function, which contains the function call. I can see from my research into this subject I am not alone in this perplexing issue. Depending on which bit of code I use inside the nested jQuery function inside the second "getAttributeValue" function I get different results. Stackoverflow helpers can see the various permutations of the code I have been trying, but are commented out for debugging, etc. The 'alert' method returns perfect clear data the way I want it. The others return nothing, 'undefined', or '[object Object]', but never the perfect clear data I want. I have been at this long enough to know I need help.

The data source is a web api / web service providing JSON data.

Here is the code:

//# This is the primary function that gathers data from a web api / web service:
    $(document).ready(function () {
        $("#loadData").click(function () {
            $.get(url, function (data) {
                var myHTMLDataTable = "<table class='table table-striped table-hover'>";
                myHTMLDataTable = myHTMLDataTable + "<tr><th>WebId</th><th>Attributes</th><th>Values</th></tr>";
                for (i = 0; i < data.Items.length; i++) {
                    myHTMLDataTable = myHTMLDataTable + "<tr>";
                    myHTMLDataTable = myHTMLDataTable + "<td class='col-sm-1'>" + (data.Items[i].WebId) + "</td>";
                    myHTMLDataTable = myHTMLDataTable + "<td class='col-sm-1'>" + (data.Items[i].Name) + "</td>";
                    myHTMLDataTable = myHTMLDataTable + "<td class='col-sm-1'>"+ getAttributeValue(data.Items[i].WebId) + "</td>"; //~ function call here
                    myHTMLDataTable = myHTMLDataTable + "</tr>";
                }
                myHTMLDataTable = myHTMLDataTable + "</table>";
                document.getElementById("myData").innerHTML = myHTMLDataTable;
            });
        });
    });

    //# This function returns a current value and uom for the target attribute:
    function getAttributeValue(attributeWebId) {
        var theEnvelopePlease = ""; //~ clear the variable
        var atrbUrl = "https://<<The Target Web API Root Address>>";
        var atrbPrefix = "streams/";
        var atrbWebId = attributeWebId;
        var atrbExtension = "/value";
        //~ Concatenate the URL used to make the request
        atrbUrl = atrbUrl + atrbPrefix + atrbWebId + atrbExtension;
        // theEnvelopePlease = $.getJSON(atrbUrl, function (data) { data.Value });
        return $.getJSON(atrbUrl, function (data) {

            //return (data.Value) + " " + (data.UnitsAbbreviation);
            //alert(data.Value + " " + data.UnitsAbbreviation);
            //theEnvelopePlease = theEnvelopePlease + (data.Value) + " " + (data.UnitsAbbreviation);
            (data.Value) + " " + (data.UnitsAbbreviation);

        });
        // return theEnvelopePlease;
    }

the JSON data being retrieved by the nested jQuery function looks like this:

    {
      "Timestamp": "2015-06-03T22:22:00Z",
      "Value": 89.660293579101563,
      "UnitsAbbreviation": "%",
      "Good": true,
      "Questionable": false,
      "Substituted": false
    }

Perhaps there is a JQuery expert reviewing this who sees my mistakes easily. Your help is much appreciated.

UPDATE: because it has been requested I want to show what I get when I use console.log: enter image description here

UPDATE: Hi @IronFlare: Thank you for your suggestion. I tried your suggestion with the revised function code as follows:

    function getAttributeValue(attributeWebId) {
        var theEnvelopePlease; //~ clear the variable
        var atrbUrl = "https://<<The Target Web API Root Address>>";
        var atrbPrefix = "streams/";
        var atrbWebId = attributeWebId;
        var atrbExtension = "/value";
        //~ Concatonate the URL used to make the request
        atrbUrl = atrbUrl + atrbPrefix + atrbWebId + atrbExtension;
        $.getJSON(atrbUrl, function (data) {
            theEnvelopePlease = (data.Value) + " " + (data.UnitsAbbreviation);
        });
        return theEnvelopePlease;
    }

and the resulting data is 'undefined' (:-c)

=======================================================

Hi @IronFlare and thank you for your suggestion. I modified the function as follows:

    function getAttributeValue(attributeWebId) {
        var theEnvelopePlease; //~ clear the variable
        var atrbUrl = "https://<<The Target Web API Root Address>>";
        var atrbPrefix = "streams/";
        var atrbWebId = attributeWebId;
        var atrbExtension = "/value";
        //~ Concatenate the URL used to make the request
        atrbUrl = atrbUrl + atrbPrefix + atrbWebId + atrbExtension;
        $.getJSON(atrbUrl, function (data) {
            theEnvelopePlease = (data.Value) + " " + (data.UnitsAbbreviation);
            console.log(data);
        });
        return theEnvelopePlease;
    }

and here is a view of the results: enter image description here

====================================================

UPDATE: For those who are following this thread I have attempted this permutation:

    //# Stackoverflow permutation 03:
    function getAttributeValue(attributeWebId) {
        var theEnvelopePlease; //~ clear the variable
        var atrbUrl = "https://<<The Target Web API Root Address>>";
        var atrbPrefix = "streams/";
        var atrbWebId = attributeWebId;
        var atrbExtension = "/value";
        //~ Concatenate the URL used to make the request
        atrbUrl = atrbUrl + atrbPrefix + atrbWebId + atrbExtension;
        theEnvelopePlease = $.getJSON(atrbUrl, function (data) {
            console.log(data.Value) + " " + (data.UnitsAbbreviation);
            return (data.Value) + " " + (data.UnitsAbbreviation);
        });
        return theEnvelopePlease;
    }

and here is a view of the results: enter image description here


Solution

  • For those who will follow this posting in the future I am pleased to provide the solution I finally found (5 days later). My key mistake centered on jQuery is essentially designed to manipulate existing HTML/DOM elements using CSS Selectors. In other languages such as C# you can procedurally call a function and get back a result and continue the rest of the program. In my previous attempts JQuery continuously returned 'undefined or '[object Object]' no matter what I tried. In this case I found my solution by first building "myHTMLDataTable" and applying a unique "id" attribute to the <td> element I wanted to fill with values. So my revised code first builds the table using a for loop, and then populates the target table cell using a second loop that calls the now working function that returns the clear data I was desperately seeking. Here is the working code:

        //# Stackoverflow SOLUTION:
        //# This is the primary function that gathers data from a web api / web service:
        $(document).ready(function () {
            $("#loadData").click(function () {
                //~ First Build the data Table:
                $.get(url, function (data) {
                    var myHTMLDataTable = "<table class='table table-striped table-hover'>";
                    myHTMLDataTable = myHTMLDataTable + "<tr><th>WebId</th><th>Attributes</th><th>Values</th></tr>";
                    for (i = 0; i < data.Items.length; i++) {
                        myHTMLDataTable = myHTMLDataTable + "<tr>";
                        myHTMLDataTable = myHTMLDataTable + "<td class='col-sm-1'>" + (data.Items[i].WebId) + "</td>";
                        myHTMLDataTable = myHTMLDataTable + "<td class='col-sm-1'>" + (data.Items[i].Name) + "</td>";
                        myHTMLDataTable = myHTMLDataTable + "<td class='col-sm-1' id='" + (data.Items[i].WebId) + "'></td>"; //~ The target table cell using the unique 'WebId'
                        myHTMLDataTable = myHTMLDataTable + "</tr>";
                    }
                    myHTMLDataTable = myHTMLDataTable + "</table>";
                    document.getElementById("myData").innerHTML = myHTMLDataTable;
                });
                //~ Second Populate the target table cell by calling the 'getAttributeValue' function in a second for loop:
                $.get(url, function (data) {
                    for (i = 0; i < data.Items.length; i++) {
                        getAttributeValue(data.Items[i].WebId);
                    }
                });
            });
        });
    
        //# This function returns a current value and uom for the target attribute directly into the target cell:
        function getAttributeValue(attributeWebId) {
            var atrbURL = "https://<<The Target Web API Root Address>>";
            var atrbPrefix = "streams/";
            var atrbWebId = attributeWebId;
            var atrbExtension = "/value";
            //~ Concatenate the URL used to make the request
            atrbUrl = atrbURL + atrbPrefix + atrbWebId + atrbExtension;
            $.getJSON(atrbUrl, function (data) {
                var myInnerValue = "";
                $.each(data, function (key, val) {
                    if (key == 'Value') {
                        myInnerValue = myInnerValue + val + " ";
                    }
                    if (key == 'UnitsAbbreviation') {
                        myInnerValue = myInnerValue + val;
                    }
                });
                $("#" + attributeWebId + "").text(myInnerValue);
            });
        }
    

    And here is a screenshot of the results: enter image description here