When the page containing the chart loads, the chart data is bound to a chart component, and the JavaScript that draws the chart is generated. When the JavaScript executes, the chart is drawn in the browser.

<apex:page controller="PieChartController" title="Pie Chart"> <apex:chart height="350" width="450" data="{!pieData}"> <apex:pieSeries dataField="data" labelField="name"/> <apex:legend position="right"/> </apex:chart> </apex:page>
The <apex:chart> component defines the chart container, and binds the component to the data source, the getPieData() controller method. The <apex:pieSeries> describes the label and data fields to access in the returned data, to label and size each data point.
Here is the associated controller:
public class PieChartController { public List<PieWedgeData> getPieData() { List<PieWedgeData> data = new List<PieWedgeData>(); data.add(new PieWedgeData('Jan', 30)); data.add(new PieWedgeData('Feb', 15)); data.add(new PieWedgeData('Mar', 10)); data.add(new PieWedgeData('Apr', 20)); data.add(new PieWedgeData('May', 20)); data.add(new PieWedgeData('Jun', 5)); return data; } // Wrapper class public class PieWedgeData { public String name { get; set; } public Integer data { get; set; } public PieWedgeData(String name, Integer data) { this.name = name; this.data = data; } } }
Providing Chart Data via a Controller Method
On the server side, write a controller method that returns a List of objects, which can be your own Apex wrapper objects as in A Simple Charting Example, sObjects, or AggregateResult objects. The method is evaluated server-side, and the results serialized to JSON. On the client, these results are used directly by <apex:chart>, with no further opportunity for processing.
To illustrate this technique with sObjects, here is a simple controller that returns a list of Opportunities, and a bar chart for their amounts:
public class OppsController { // Get a set of Opportunities public ApexPages.StandardSetController setCon { get { if(setCon == null) { setCon = new ApexPages.StandardSetController(Database.getQueryLocator( [SELECT name, type, amount, closedate FROM Opportunity])); setCon.setPageSize(5); } return setCon; } set; } public List<Opportunity> getOpportunities() { return (List<Opportunity>) setCon.getRecords(); } }
<apex:page controller="OppsController"> <apex:chart data="{!Opportunities}" width="600" height="400"> <apex:axis type="Category" position="left" fields="Name" title="Opportunities"/> <apex:axis type="Numeric" position="bottom" fields="Amount" title="Amount"/> <apex:barSeries orientation="horizontal" axis="bottom" xField="Name" yField="Amount"/> </apex:chart> <apex:dataTable value="{!Opportunities}" var="opp"> <apex:column headerValue="Opportunity" value="{!opp.name}"/> <apex:column headerValue="Amount" value="{!opp.amount}"/> </apex:dataTable> </apex:page>
Providing Chart Data Using a JavaScript Function
Instead of feeding data directly into the chart, you can provide the <apex:chart> component with the name of a JavaScript function that provides the data. The actual JavaScript function is defined in or linked from your Visualforce page. This function has the opportunity to manipulate the results before passing it to <apex:chart>, or to perform other user interface or page updates.
The JavaScript function must take a callback function as a parameter, and invoke the callback with the function's data result object. The simplest working JavaScript function looks like this:
<apex:page> <script> function getRemoteData(callback) { PieChartController.getRemotePieData(function(result, event) { if(event.status && result && result.constructor === Array) { callback(result); } }); } </script> <apex:chart data="getRemoteData" ...></apex:chart> </apex:page>
To support this chart, add the following controller method to the PieChartController class defined in A Simple Charting Example:
@RemoteAction public static List<PieWedgeData> getRemotePieData() { List<PieWedgeData> data = new List<PieWedgeData>(); data.add(new PieWedgeData('Jan', 30)); data.add(new PieWedgeData('Feb', 15)); data.add(new PieWedgeData('Mar', 10)); data.add(new PieWedgeData('Apr', 20)); data.add(new PieWedgeData('May', 20)); data.add(new PieWedgeData('Jun', 5)); return data; }
See JavaScript Remoting for Apex Controllers for more information about using JavaScript remoting in Visualforce.
Providing Chart Data via a JavaScript Array
You can use Visualforce charting with non-Salesforce data sources by building a JavaScript array, in your own JavaScript code in your page, and providing the name of that array to <apex:chart>.
<apex:page> <script> // Build the chart data array in JavaScript var dataArray = new Array(); dataArray.push({'data1':33,'data2':66,'data3':80,'name':'Jan'}); dataArray.push({'data1':33,'data2':66,'data3':80,'name':'Feb'}); // ... </script> <apex:chart data="dataArray" ...></apex:chart> </apex:page>
When using this technique, if your data is coming from another source you may not need any server-side Apex code at all.
Chart data provided by an Apex method should be a List of uniform objects. These objects may be simple wrappers, sObjects, or AggregateResult objects. Every object in the List must contain all fields referenced in the <apex:chart> component hierarchy that is bound to that data source. If all fields are not provided, a client-side JavaScript error is thrown, which you can view in a JavaScript console such as Firebug.
Chart data provided by JavaScript methods should be a JavaScript array of arrays. See Providing Chart Data via a JavaScript Array for details.