{"id":6987,"date":"2015-10-01T12:15:48","date_gmt":"2015-10-01T09:15:48","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=6987"},"modified":"2015-09-25T22:30:11","modified_gmt":"2015-09-25T19:30:11","slug":"asynchronous-google-chart-data-jquery-grails","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/","title":{"rendered":"Asynchronous Google Chart Data With jQuery in Grails"},"content":{"rendered":"<p><a href=\"https:\/\/developers.google.com\/chart\">Google Charts<\/a>\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps.<\/p>\n<p>&nbsp;<br \/>\n&nbsp;<br \/>\n&nbsp;<br \/>\n&nbsp;<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-piechart.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-7047\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-piechart.png\" alt=\"google-charts-piechart\" width=\"489\" height=\"341\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-piechart.png 489w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-piechart-300x209.png 300w\" sizes=\"(max-width: 489px) 100vw, 489px\" \/><\/a><\/p>\n<p>I needed a way to create the required\u00a0data for a chart on the server-side, instead of in-lining it in the JavaScript itself \u2014 as seen in many of the examples.<\/p>\n<h3>Why asynchronously?<\/h3>\n<p>Although in the example below we\u2019re using a small\u00a0hard-coded dataset, for which there\u2019s no real need to have this done asynchronously, this might not always be the case in the real world. Loading in data asynchronously improves the user experience especially if calculating or getting the data for the chart might take significant time. E.g. the\u00a0page containing\u00a0the charts is displayed\u00a0quickly in the browser \u2014 while the actual graphs are rendered when the data comes in.<\/p>\n<p>Sometimes you might even have multiple charts on\u00a0a page, which leans even more to a situation where the <em>page response time<\/em> can become too lengthy if we have to wait on all graph data to be fetched or computed first before rendering the page.<\/p>\n<p>So I took the PHP example and re-created it in a\u00a0Grails way. I\u2019m also taking care of exceptional situations and logging errors on the client side. This is just an example which works for me \u2013 there might be other approaches.<\/p>\n<h3>The HTML<\/h3>\n<p>For simplicity\u2019s sake I just took the example code quite literally and put it in the head section of a Grails GSP page.<\/p>\n<p>For those wondering whether or not they can download the JS files and have it processed with the Asset Pipeline plugin. The answer is: <em>no<\/em>. Per the <a href=\"https:\/\/google-developers.appspot.com\/chart\/interactive\/faq\">FAQ<\/a>:<\/p>\n<p>Sorry; our <a href=\"https:\/\/google-developers.appspot.com\/chart\/terms\">terms of service<\/a> do not allow you to download and save or host the google.load or google.visualization code.<\/p>\n<p>So we <em>have<\/em> to include the <code>jsapi<\/code> JavaScript in the head \u2013 which you can do on your specific chart page (as seen below) or in your <code>main.gsp<\/code> layout. If your\u00a0Grails application by default is still shipped with jQuery as a dependency, then you don\u2019t need to include it\u00a0explicitly on your page ofcourse \u2013 but I have left the\u00a0<code>jquery.min.js<\/code> line below intact for now.<\/p>\n<pre class=\"brush:html\">&lt;%@ page contentType=\"text\/html;charset=UTF-8\" %&gt;\r\n&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n  &lt;meta charset=\"utf-8\" \/&gt;\r\n  &lt;meta name=\"layout\" content=\"main\" \/&gt;\r\n  &lt;script type=\"text\/javascript\" src=\"https:\/\/www.google.com\/jsapi\"&gt;&lt;\/script&gt;\r\n  &lt;script type=\"text\/javascript\" src=\"\/\/ajax.googleapis.com\/ajax\/libs\/jquery\/1.11.1\/jquery.min.js\"&gt;&lt;\/script&gt;\r\n  &lt;script&gt;\r\n\r\n    \/\/ Load the Visualization API and the piechart package.\r\n    google.load('visualization', '1.1', {'packages':['corechart']});\r\n\r\n    \/\/ Set a callback to run when the Google Visualization API is loaded.\r\n    google.setOnLoadCallback(drawChart);\r\n\r\n    function drawChart() {\r\n      var jsonData = $.ajax({\r\n        url: \"${createLink(controller:'chart', action:'toppings')}\",\r\n        dataType: \"json\",\r\n        async: false\r\n      }).responseText;\r\n\r\n      \/\/ Create our data table out of JSON data loaded from server.\r\n      var data = new google.visualization.DataTable(jsonData);\r\n\r\n      \/\/ Instantiate and draw our chart, passing in some options.\r\n      var chart = new google.visualization.PieChart(document.getElementById('chart_div'));\r\n      chart.draw(data, {width: 400, height: 240});\r\n    }\r\n  &lt;\/script&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n\r\n\r\n&lt;div id=\"chart_div\"&gt;&lt;\/div&gt;\r\n\r\n\r\n    \r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>The <code>$.ajax<\/code> statement is jQuery\u2019s way of performing an asynchronous HTTP (Ajax) request. In the url I\u2019m creating a link \u2013 with Grails\u2019 <code>createLink<\/code>-tag \u2013 to the <code>ChartController<\/code> and <code>toppings<\/code> action responsible for giving me the JSON chart data.<\/p>\n<p>Initially you won\u2019t see a thing when the page is rendered. However, as soon as the <code>&lt;script&gt;<\/code> block is encountered, the browser interprets it, loads the Google libraries which invokes our callback function <code>drawChart<\/code>. This callback has jQuery make a new request to fetch the chart data. The response of the request is loaded into a variable <code>jsonData<\/code> which is passed to the constructor of Google\u2019s own <code>DataTable<\/code> JS class.<\/p>\n<p>The chart is drawn and the HTML div \u2013 with id <em>chart_id<\/em> \u2013 is updated with a chart.<\/p>\n<h3>The JSON<\/h3>\n<p>The JSON is the result of calling controller action below:<\/p>\n<pre class=\" brush:groovy\">import grails.converters.JSON\r\n \r\nclass ChartController {\r\n \r\n  def toppings() {\r\n \r\n    def cols = [\r\n      [label: &amp;quot;Topping&amp;quot;, type:&amp;quot;string&amp;quot;],\r\n      [label: &amp;quot;Slices&amp;quot;, type:&amp;quot;number&amp;quot;]\r\n    ]\r\n \r\n    def rows = [\r\n      , [v:3]]],\r\n      , [v:1]]],\r\n      , [v:1]]],\r\n      , [v:1]]],\r\n      , [v:2]]]\r\n    ]\r\n \r\n    def data = [cols: cols, rows: rows]\r\n    render data as JSON\r\n  }\r\n}<\/pre>\n<p>It\u2019s all Maps in Maps in Lists etc. in Groovy syntax. If you\u2019re wondering what these \u201cc\u201d and \u201cv\u201d values mean; they\u2019re the essential properties for defining an array of cells in that row and defining the value for that cell. There are more <a href=\"https:\/\/developers.google.com\/chart\/interactive\/docs\/reference#dataparam\">parameters<\/a>, which you can use to tweak formatting and more.<\/p>\n<p>If you\u2019ve got the nesting right, just using Grails\u2019\u00a0<code>grails.converters.JSON<\/code> will do the trick to get this structure rendered as valid JSON, something our Google Chart JavaScript understands very well.<\/p>\n<p>By accessing your url directly in the browser on e.g.<\/p>\n<div>\n<div id=\"highlighter_555664\" class=\"syntaxhighlighter nogutter plain\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"plain plain\"><a href=\"http:\/\/localhost:8080\/yourapp\/chart\/toppings\">http:\/\/localhost:8080\/yourapp\/chart\/toppings<\/a><\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>you can inspect the raw JSON:<\/p>\n<pre class=\" brush:js\">{\"cols\":[{\"label\":\"Topping\",\"type\":\"string\"},{\"label\":\"Slices\",\"type\":\"number\"}],\"rows\":[{\"c\":[{\"v\":\"Mushrooms\"},{\"v\":3}]},{\"c\":[{\"v\":\"Onions\"},{\"v\":1}]},{\"c\":[{\"v\":\"Olives\"},{\"v\":1}]},{\"c\":[{\"v\":\"Zucchini\"},{\"v\":1}]},{\"c\":[{\"v\":\"Pepperoni\"},{\"v\":2}]}]}<\/pre>\n<p>You could create some helper methods to make creating this data somewhat easier. E.g. to remove the repetition, you could use a Groovy closure like this:<\/p>\n<pre class=\" brush:groovy\">def rows = []\r\ndef addRow = { name, value -&gt;            \r\n    rows &lt;&lt; , [v: value]]]\r\n}\r\n \r\naddRow(\"Mushrooms\", 3)\r\naddRow(\"Onions\", 1)\r\naddRow(\"Olives\", 1)\r\naddRow(\"Zucchini\", 1)\r\naddRow(\"Pepperoni\", 2)\r\n<\/pre>\n<p>Upon accessing the page I successfully see my pie chart.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-piechart1.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-7267\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-piechart1.png\" alt=\"google-charts-piechart\" width=\"300\" height=\"209\" \/><\/a><\/p>\n<h3>Not done yet<\/h3>\n<p>However, I\u2019m also getting a <em>JavaScript warning<\/em>:<\/p>\n<blockquote><p>Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user\u2019s experience. For more help, check<a href=\"http:\/\/xhr.spec.whatwg.org\/\" rel=\"nofollow\">http:\/\/xhr.spec.whatwg.org\/<\/a>.<\/p><\/blockquote>\n<p>Seems the example I took still had <code>async: false<\/code>\u00a0in place. Overlooked it. Just set <code>async<\/code>explicitly to <em>true<\/em> (or leave it out \u2013 since <em>it defaults to true<\/em>) to make it do its call asynchronously.<\/p>\n<pre class=\" brush:js\">var jsonData = $.ajax({\r\n  url: &amp;quot;${createLink(controller:'chart', action:'toppings')}&amp;quot;,\r\n  dataType: &amp;quot;json&amp;quot;,\r\n  async: true\r\n}).responseText;\r\n \r\n\/\/ Create our data table out of JSON data loaded from server.\r\nvar data = new google.visualization.DataTable(jsonData);<\/pre>\n<p>Unfortunately, this causes the AJAX call not to block any more and immediately pass<code>jsonData<\/code> to the <code>DataTable<\/code> constructor \u2013 even before any data actually came back from the controller. At this point <code>jsonData<\/code> is <em>undefined<\/em> and the Google Chart fails with an error \u201cTable has no columns\u201d.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-failure-table-has-no-columns.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-7268\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-failure-table-has-no-columns.png\" alt=\"google-charts-failure-table-has-no-columns\" width=\"233\" height=\"30\" \/><\/a><\/p>\n<p>To properly fix this in jQuery the documentation on <a href=\"http:\/\/api.jquery.com\/jquery.ajax\/\">jquery.ajax<\/a> suggests to use the <em>promises<\/em> of the <code>jqXHR<\/code> object. We have a few, such as <code>done<\/code> \u2013 a callback which is fired when the operation successfully completed.<\/p>\n<p>If we\u2019re in the callback, we know we have the JSON data.\u00a0Here\u2019s after the changes:<\/p>\n<pre class=\" brush:js\">function drawChart() {\r\n  $.ajax({\r\n    url: \"${createLink(controller:'chart', action:'toppings')}\",\r\n    dataType: \"json\"\r\n  }).done(function(jsonData) {\r\n  \r\n    \/\/ Create our data table out of JSON data loaded from server.\r\n    var data = new google.visualization.DataTable(jsonData);\r\n \r\n    \/\/ Instantiate and draw our chart, passing in some options.\r\n    var chart = new google.visualization.PieChart(document.getElementById('chart_div'));\r\n    chart.draw(data, {width: 400, height: 240});\r\n  });\r\n}\r\n<\/pre>\n<p>Great!<\/p>\n<h3>Exceptional situations<\/h3>\n<p>But where not there yet. What if the calculation of the chart data fails due to some reason? E.g.<code>ChartController<\/code> fails at run-time? Right now, in this case we\u2019re getting an HTTP 500 (\u201cInternal Server Error\u201d) for that asynchronous request and consequently NO chart is drawn \u2013 just an empty space on the page. In these exceptional situations we could at least inform the user where his chart has gone to provide a better user experience.<\/p>\n<p>We can use the <code>fail<\/code> promise for this. It\u2019s a special method called when the request is \u201crejected\u201d. It gets passed a few parameters, such as <code>jqXHR<\/code>, <code>textStatus<\/code> and <code>errorThrown<\/code>, but there\u2019s nothing really interesting to get from these right now when an Internal Server Error occurs. The reason of failure can be anything.<\/p>\n<p>So, things could be as simple as displaying an alert.<\/p>\n<pre class=\" brush:js\">}).done(function(jsonData) {\r\n  ...\r\n}).fail(function() {\r\n  alert('Failed to load data for the chart.');\r\n});<\/pre>\n<p>This is not really a \u201cbetter user experience\u201d of course <span class=\"wp-smiley wp-emoji wp-emoji-smile\" title=\":-)\">:-)<\/span> We need a way to leverage the existing error reporting, such as the earlier error when the chart failed with \u201cTable has no columns\u201d. The Google Chart API docs describe several functions to help you <a href=\"https:\/\/developers.google.com\/chart\/interactive\/docs\/reference#errordisplay\">display error messages<\/a> to users.<\/p>\n<p>It seems there are some static function in the <code>google.visualization.errors<\/code> namespace we can leverage, such as <code>addError<\/code>. This function accepts a minimum amount of parameters: the container, our chart DOM element, and a message, so it can display an error block in the visualization.<\/p>\n<p>Let\u2019s put it to use:<\/p>\n<pre class=\" brush:js\">$.ajax({\r\n  url: \"${createLink(controller:'chart', action:'toppings')}\",\r\n  dataType: \"json\"\r\n}).done(function(jsonData) {\r\n                       \r\n  \/\/ Create our data table out of JSON data loaded from server.\r\n  var data = new google.visualization.DataTable(jsonData);\r\n \r\n  \/\/ Instantiate and draw our chart, passing in some options.\r\n  var chart = new google.visualization.PieChart(chartDiv);\r\n  chart.draw(data, {width: 400, height: 240});\r\n \r\n}).fail(function() {\r\n  google.visualization.errors.addError(chartDiv, \r\n    \"Failed to load data for the chart.\");\r\n});\r\n<\/pre>\n<p>I\u2019ve extracted the chart <code>div<\/code> element to a higher-level to be able to re-use it in both <code>done()<\/code> and<code>fail()<\/code> promises.<\/p>\n<p>The error would now be displayed where the chart would be:<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-failure-failed-to-load-data-for-the-chart.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-7269\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/google-charts-failure-failed-to-load-data-for-the-chart.png\" alt=\"google-charts-failure-failed-to-load-data-for-the-chart\" width=\"283\" height=\"30\" \/><\/a><\/p>\n<h3>Development tip<\/h3>\n<p>You can optionally use the <code><a href=\"https:\/\/developers.google.com\/chart\/interactive\/docs\/datatables_dataviews#datatabletocsv\">google.visualization.dataTableToCsv<\/a><\/code> helper function to display the loaded data for development purposes in the browser\u2019s console.<\/p>\n<pre class=\" brush:xml\">\r\n...\r\nchart.draw(data, options);\r\n \r\n&lt;g:if env=&quot;development&quot;&gt;\r\n\/\/ Debug the output to the browser's console\r\nif (console &amp;&amp; console.log) {\r\n var csv = google.visualization.dataTableToCsv(data);\r\n console.log(csv);\r\n}\r\n&lt;\/g:if&gt;\r\n<\/pre>\n<p>That\u2019s it. Happy charting!<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/tedvinke.wordpress.com\/2015\/09\/07\/asynchronous-google-chart-data-with-jquery-in-grails\/\">Asynchronous Google Chart Data With jQuery in Grails<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/wcg\/\">WCG partner<\/a> Ted Vinke at the <a href=\"http:\/\/tedvinke.wordpress.com\/\">Ted Vinke&#8217;s Blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Google Charts\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps. &nbsp; &nbsp; &nbsp; &nbsp; I needed a way to create the required\u00a0data for a chart on the server-side, instead of in-lining it in the JavaScript itself \u2014 as seen in many of the examples. Why asynchronously? Although &hellip;<\/p>\n","protected":false},"author":98,"featured_media":919,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[240],"class_list":["post-6987","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-jquery","tag-grails"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Asynchronous Google Chart Data With jQuery in Grails - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Google Charts\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps. &nbsp; &nbsp;\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Asynchronous Google Chart Data With jQuery in Grails - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Google Charts\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps. &nbsp; &nbsp;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-10-01T09:15:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Ted Vinke\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ted Vinke\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/\"},\"author\":{\"name\":\"Ted Vinke\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/248f1e47b008c8e7f565221d26a22c51\"},\"headline\":\"Asynchronous Google Chart Data With jQuery in Grails\",\"datePublished\":\"2015-10-01T09:15:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/\"},\"wordCount\":1129,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg\",\"keywords\":[\"Grails\"],\"articleSection\":[\"jQuery\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/\",\"name\":\"Asynchronous Google Chart Data With jQuery in Grails - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg\",\"datePublished\":\"2015-10-01T09:15:48+00:00\",\"description\":\"Google Charts\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps. &nbsp; &nbsp;\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JavaScript\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"jQuery\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/jquery\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Asynchronous Google Chart Data With jQuery in Grails\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/248f1e47b008c8e7f565221d26a22c51\",\"name\":\"Ted Vinke\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/2c3187ff528137f4f4318dafd2d60d8832e6b5b0f3f38af9ae20ef90d9df8319?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/2c3187ff528137f4f4318dafd2d60d8832e6b5b0f3f38af9ae20ef90d9df8319?s=96&d=mm&r=g\",\"caption\":\"Ted Vinke\"},\"description\":\"Ted is a Java software engineer with a passion for Web development and JVM languages and works for First8, a Java Web development company in the Netherlands.\",\"sameAs\":[\"http:\/\/tedvinke.wordpress.com\/\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/ted-vinke\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Asynchronous Google Chart Data With jQuery in Grails - Web Code Geeks - 2026","description":"Google Charts\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps. &nbsp; &nbsp;","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/","og_locale":"en_US","og_type":"article","og_title":"Asynchronous Google Chart Data With jQuery in Grails - Web Code Geeks - 2026","og_description":"Google Charts\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps. &nbsp; &nbsp;","og_url":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2015-10-01T09:15:48+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg","type":"image\/jpeg"}],"author":"Ted Vinke","twitter_card":"summary_large_image","twitter_creator":"@webcodegeeks","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Ted Vinke","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/"},"author":{"name":"Ted Vinke","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/248f1e47b008c8e7f565221d26a22c51"},"headline":"Asynchronous Google Chart Data With jQuery in Grails","datePublished":"2015-10-01T09:15:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/"},"wordCount":1129,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg","keywords":["Grails"],"articleSection":["jQuery"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/","url":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/","name":"Asynchronous Google Chart Data With jQuery in Grails - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg","datePublished":"2015-10-01T09:15:48+00:00","description":"Google Charts\u00a0is an awesome platform to create great-looking interactive charts, from simple scatter plots to timelines or treemaps. &nbsp; &nbsp;","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/jquery-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/javascript\/jquery\/asynchronous-google-chart-data-jquery-grails\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JavaScript","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/"},{"@type":"ListItem","position":3,"name":"jQuery","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/jquery\/"},{"@type":"ListItem","position":4,"name":"Asynchronous Google Chart Data With jQuery in Grails"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/248f1e47b008c8e7f565221d26a22c51","name":"Ted Vinke","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/2c3187ff528137f4f4318dafd2d60d8832e6b5b0f3f38af9ae20ef90d9df8319?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2c3187ff528137f4f4318dafd2d60d8832e6b5b0f3f38af9ae20ef90d9df8319?s=96&d=mm&r=g","caption":"Ted Vinke"},"description":"Ted is a Java software engineer with a passion for Web development and JVM languages and works for First8, a Java Web development company in the Netherlands.","sameAs":["http:\/\/tedvinke.wordpress.com\/"],"url":"https:\/\/www.webcodegeeks.com\/author\/ted-vinke\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/6987","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/98"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=6987"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/6987\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/919"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=6987"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=6987"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=6987"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}