从异步AJAX响应加载Google Chart

时间:2011-12-09 16:12:46

标签: php ajax google-visualization

在旧的Google Chart API中,可以使用PHP来呈现图表,甚至还有一个包装器来执行此操作: http://code.google.com/p/gchartphp/

但是使用新的Chart API http://code.google.com/apis/chart/ 这会生成更多更漂亮的图表,但只能在浏览器中加载javascript。

我想要实现的效果是通过AJAX向服务器提交多项选择表单,让PHP更新数据库服务器,然后返回更新的图表。

在旧的API方式中我可以做到这一点。但是以新的方式,我将javascript返回到浏览器并将其附加到文档以呈现图表。它不会因此而执行。我相信我可以eval()这个javascript,但这是不好的形式不是因为有人可以做一些讨厌的东西,他们不能 - eval()服务器端响应?

我怎样才能克服这一点?有没有PHP包装器来帮助这个?还是有另一个我忽略的原因?

非常感谢

3 个答案:

答案 0 :(得分:6)

我最终解决这个问题的方式非常明显。我只需要超越自己的想法,从另一个角度来看待它。

我正在努力处理数据库信息并使用PHP在服务器端创建Google Chart(在本例中为饼图)。然后将其作为AJAX响应返回。

实际上我需要做的就是返回创建饼图所需的数据(以及一些额外的元数据,例如目标元素id)。我这样做是为了JSON。然后,通过浏览Google Charts文档,我能够找到如何使用客户端javascript来加载返回的JSON数据来触发API。然后让Google代码渲染图表客户端 - 所以我基本上将所有渲染责任转移到客户端浏览器。这是旧图表和新图表API的不同之处。

需要大量的试验和错误以及来自Firebug的大量帮助。值得一提的一个重大绊脚石是,您需要在收到JSON响应之前加载所有Google JSAPI - 以便初始页面呈现 - 并且您必须执行以下操作:

google.load("visualization", "1", {packages:["corechart"]});

确保在页面呈现时加载。如果在页面完全呈现后调用此页面,则页面将重新加载。

希望这有助于某人。

答案 1 :(得分:3)

感谢 andyg1 Ascendant ,我能够让它像这样工作(使用PrototypeJS而不是jQuery,但想法是一样的)。由于这一点并不明显,我将展示所有步骤。

Ajax端点只返回json,看起来像这样(.NET MVC模板)。请注意,我发现我必须引用Google's documentation未建议的所有内容:

<% 
Response.Headers.Add("Content-type", "text/json");
Response.AddHeader("Content-type", "application/json");
%>
{
  "cols": [
    {"id": "col_1", "label": "Date", "type": "string"},
    {"id": "col_2", "label": "Score", "type": "number"}
  ],
  "rows": [
    <%
    int index = 0;
    foreach(KeyValuePair<string, double> item in Model.Performance ) { %>
      {"c":[{"v":"<%= item.Key %>"}, {"v":<%= item.Value %>}]}<%= (index == Model.Performance.Count - 1) ? "" : "," %>
      <% index++; %>
      <% 
    } 
    %>
  ]
}

然后母版页包含:

<script type="text/javascript" src="https://www.google.com/jsapi"></script> 
<script type="text/javascript" src="/js/myJavascriptFile.js" />

然后在myJavascriptFile.js中(请注意,initialize方法的最后一行是google.setOnLoadCallback,它调用我的类中的方法而不是drawChart):

google.load('visualization', '1', {'packages':['corechart']});
var colors = {'blue': '#369', 'red': '#c22', 'green': '#283', 'yellow': '#c91'};

var MyClass = Class.create({

  initialize: function() {
    ... 
    google.setOnLoadCallback(this.getTeamCharts);
  },

  getTeamCharts: function () {
    $$(".chart-wrapper").each(function (div) {
      var chartData = div.getData();
      var parameters = {
        ...
      };

      new Ajax.Request('/endpoints/TeamChart.aspx', {
        method: 'get',
        parameters: parameters,
        onSuccess: function(transport) {
            var jsonData = transport.responseJSON;
            var data = new google.visualization.DataTable(jsonData);
            var chartColor = colors[parameters.TeamColor];
            var chartDivId = 'chart_div_' + parameters.TeamIdAsString;

            // Set chart options
            var options = {
              'chartArea': {'left':'15%','top':'15%','width':'80%','height':'70%'},
              'legend': {'position': 'none'},
              'lineWidth': 3,
              'width': 262, 
              'height': 180,
              'colors': [chartColor]
            };

            // Instantiate and draw our chart, passing in some options.
            var chart = new google.visualization.LineChart(document.getElementById(chartDivId));
            chart.draw(data, options);
        }
      });
    });
  }

});

document.observe("dom:loaded", function () {
  var thing = new MyClass();
});

我确信它可以进一步改进但是有效!

答案 2 :(得分:0)

过去我使用隐藏字段处理这样的情况,该隐藏字段作为请求的一部分返回,其中包含您想要的任何格式的相关数据。没有返回javascript。在ajax的成功回调中,您将从该输入中获取并处理数据。

编辑:

基本上,如果您直接通过ajax html更新页面而您不想更改该功能的方式,请将ajax响应的一部分作为隐藏输入

<input type="hidden" name="yourhiddeninputname" id="yourhiddeninputname" 
   value="whatever|data|you|want,blah,blah,blah" /> 

然后,一旦html被注入你的页面,你就会做类似的事情

var yourdata = document.getElementById('yourhiddeninputname').value;
// do stuff with your data here.

这是最好的选择吗?我不确定。这真的取决于你如何处理你的ajax。我的原始评论来自ASP.NET背景,通常,您指望某些类实例为您生成html,并且您从生成的实际html(以及其他内容)中抽象出来。当然,还有其他方法可以解决这个问题,特别是如果您可以完全控制如何呈现和处理AJAX响应。