2

I am submitted a getJSON request to a controller in my application, this controller is returning valid JSON with 2 "applications." I know this for a fact as if I move the alert statement to within jQuery's each function it will give me the expected result.

I am attempting to store this data within a multidimensional array to later be used with extJS' Menu Control.

Code:

Ext.onReady(function() {
    var applicationList = [];
    jQuery.getJSON('index.php/applications', function(data) {
        jQuery.each(data.applications, function (i, app) {
            applicationList[i] = [];
            applicationList[i]['text'] = app['title'];
            applicationList[i]['id'] = app['slug'];
        });
    });
    alert(applicationList[0]['text']);

    var applicationMenu = Ext.menu.Menu({
        items: applicationList
    });
});

JSON Response:

{"applications":[{"slug":"test","title":"Test"},{"slug":"hardware","title":"Hardware"}]}

Expected Result:

Test

Actual Result (from Firebug):

applicationList[0] is undefined

If I replace the alert() above, with the following code I get one alert window with the text "remove":

for (p in applicationList) {
    alert(p);
}

Now, my thinking is that the JSON request isn't completing in-time for the alert() so I'll use a named callback function to ensure the request has completed:

var data;
jQuery.getJSON('index.php/applications', get_applications(data));

function get_applications(data) {
    jQuery.each(data.applications, function (i, app) {
        applicationList[i] = [];
        applicationList[i]['text'] = app['title'];
        applicationList[i]['id'] = app['slug'];
    });
};

But now Firebug is telling me that data is undefined...

I feel like I am almost there, but I've been almost there for the past hour and I feel as if I am just polluting the source now in trying to get it to work.

Michael Wales
  • 10,360
  • 8
  • 28
  • 28

4 Answers4

6

This should do it:

Ext.onReady(function() {
    var applicationList = [];
    var applicationMenu;

    jQuery.getJSON('index.php/applications', function(data) {
        jQuery.each(data.applications, function (i, app) {
                applicationList[i] = [];
                applicationList[i]['text'] = app['title'];
                applicationList[i]['id'] = app['slug'];
        });

        applicationMenu = Ext.menu.Menu({
            items: applicationList
        });
    });
});

Your thinking is right; the reason it is not working is because AJAX is an asynchronous process and as you fire off the getJSON function javascript keeps on trucking along. Your solution doesn't work because making it a named callback is not changing the fact that it won't be fired until you've already tried to initialize the Menu. All my solution is doing is moving the Menu initilization code INSIDE the callback, as it is then and only then that you will have access to the filled out applicationList.

Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • the "applicationList" nd "applicationMenu" variable definitions can (and probably should) be moved into your getJSON anonymous function. – Matt Huggins Oct 01 '09 at 07:01
3

You're right, you should use your "applicationList" variable only after the getJSON callback has finished.

You should call Ext.menu.Menu() inside your getJSON callback, after jQuery.each().

Seb
  • 24,920
  • 5
  • 67
  • 85
1

Paolo Bergantino's solution should work, but you can also do it your way, using a named callback function -- you just made some small errors in your code:

  1. data should not be declared as a variable -- data in "function get_applications(data)" just stands for whatever .getJSON returns
  2. The callback function in .getJSON should just be the name of the function, without (data)

Here's the corrected code:

jQuery.getJSON('index.php/applications', get_applications);

function get_applications(data) {
        jQuery.each(data.applications, function (i, app) {
                applicationList[i] = [];
                applicationList[i]['text'] = app['title'];
                applicationList[i]['id'] = app['slug'];
        });
};
Olivia
  • 11
  • 1
0
$.getJSON("getq2.php", {
  yr: year,
  typ: type
}, function(data) {
  var items1 = new Array();
  var j = 0;
  for (var i in data) {
    var items = new Array();

    items.push(data[i][0], Number(data[i][1]));
    items1[j++] = items;
  }
  console.log(items1);
  var plot1 = jQuery.jqplot('chartContainer', [items1], {
    seriesDefaults: {

      // Make this a pie chart.
      renderer: jQuery.jqplot.PieRenderer,
      rendererOptions: {
        startAngle: 180,
        sliceMargin: 2,
        dataLabelThreshold: 2,

        // Put data labels on the pie slices.
        // By default, labels show the percentage of the slice.
        showDataLabels: true,

      }
    },
    grid: {
      borderWidth: 0,
      shadow: false,
      background: '#d8d6cb'
    },
    legend: {
      placement: 'outside',
      show: true,
      location: 'e',
      background: 'transparent',
      marginRight: '30px'
    }
  });
});
Mickael Lherminez
  • 679
  • 1
  • 10
  • 29