Just before Dreamforce, Dave Carroll and I hosted the Winter ’13 developer preview webinar talking about what’s new to the platform. One of the major features that became generally available was Visualforce Charting. Visualforce Charting is an easy way to create customized business charts, based on data sets you create directly from SOQL queries or by building the data set in JavaScript. Sandeep Bhanot posted an article a while back going over how to build layered line and bar charts with a controller, and in this article I am going to go over new chart types and techniques.

Visualforce charts are rendered client-side using JavaScript. This allows charts to be animated and, on top of that, chart data can load and reload asynchronously which can make the page feel more responsive. In this article, I want to highlight a few of the new chart types that were recently released, and demonstrate some of the advanced rendering capabilities.

The Gauge Chart

You can build this data set similarly to how you would build a data set for a pie chart. The main difference is that there is only one list element to build the complete chart. In the example below, I am summarizing the total amount of opportunities closed this month related to an account.

The structure for building this chart is almost identical to what we’ve seen already with the previously existing chart types. To populate the chart with data, you need to build a list with an inner class (aka wrapper class). One thing to note, your wrapper class must have a ‘name’ field if you want to display a tooltip on hover. Once your data set is constructed, you can output it on your Visualforce page  with a few simple components:

The chart to the left is what the output looks like initially. If you try to use CSS to manipulate the width and/or height frame, you will get to watch the frame dynamically continue to cut off your text. Thankfully the frame problem can be alleviated using a little bit of JavaScript.

First give your chart a name. This makes the component recognizable as a JavaScript object for additional configurations or dynamic operations. Note this name must be unique across all chart components, and if the encompassing top-level component (<apex:page> or <apex:component>) is namespaced, the chart name will be prefixed with it (ie. MyNamespace.MyChart).

In my page above I named the chart “MyChart.” I was able to manipulate all of the axes by using a simple on() method call. The code below is the snippet that I put into my page, and the picture below that displays the new results.

The Radar Chart

The radar chart is a unique chart to build. In order to create this data set, you will need to create a list of maps rather than using a wrapper class. For my example, I am plotting customer satisfaction ratings related to an account. Each of these ratings are stored as number fields to plot on a circle. In Winter ’13 you can now query field sets, so I have put all of the rating fields from my account into a field set (named RadarSet) to build out my chart.

One thing to note, you don’t have to use a field set to build this  chart. I used a field set because I thought it would be more elegant to dynamically query for and generate chart data. You could build your own hardcoded SOQL query if you wanted, but by using field sets you can easily change the fields in the query without having to change the code, or you could also take this code and make another radar chart quickly off of a different field set.

To explain the code above, I have broke down the order of operations in my class as follows:

  • Build a dynamic SOQL statement using fields from my RadarSet field set (lines 9-21)
  • Save all of the field set API names to a list for reference to use with the describe maps (line 19)
  • Generate describe information based off of query results (lines 23-25)
  • Create a map of labels and API names (lines 28-31)
  • Use field set list to map labels to values returned from the query (line 30)
  • Store these to a map of objects for each data point, and add that to the overall map which will populate the chart on the page (lines 34 to 42)

The Visualforce page is again pretty trivial. In addition, some of my field labels were a little long and were cut off by the frame again. The JavaScript hack above didn’t do the trick, but there is a static ID associated with the frame that cuts off the chart, so I was able to apply sizing to that explicitly so that the chart would render properly.

The Scatter Chart with JavaScript Remoting

The final graph I’m going to go over is the scatter series chart. In addition to feeding data directly into the chart from a standard getter method in your Apex class, you can provide the component with the name of a JavaScript function that generates the data. The actual JavaScript function is defined in or linked from your Visualforce page and has the opportunity to manipulate the results before passing it to your chart, or to perform other user interface or page updates.

In my example I am querying for all opportunities related to a campaign and plotting them on a graph with the x-axis displaying the expected revenue value and the y-axis displaying the actual amount. By default it will display all opportunities, but I am using an actionFunction on a selectList to rerender the chart to display records of a specific lead source.

First, let’s take a look at my JavaScript function on my Visualforce page constructing the chart data.

In my function I first call a remote action, a method inside my Apex class, called getRemoteScatterData. After I check that the result returned from the remote action is valid, I loop through the results to either save everything if ‘All’ is selected or only the opportunities with the selected lead source. I used a jQuery selector to grab the selected value because Visualforce appends extra characters to the id of the selectList.

By default my selectList shows everything, but you could easily add in more JavaScript functionality like adding a show/hide to only show the chart after a value is selected. There is a lot of flexibility with how you want the chart to render in here.

My remote action (displayed below) is very simple in comparison. It runs the query on all opportunities related to the campaign and then saves the result to a list using my wrapper class. The values being sent to my wrapper class are stored to variables ‘name’, ‘type’, ‘expected’, and ‘amount’ respectively. This is why in my JavaScript function I can reference result[i].type.

Back on my Visualforce page, I have two main sections other than the JavaScript that I want to breakdown. First, we have the chart. This pulls in the ‘newResultList’ returned from the callback in my getRemoteData function. The component does some behind-the-scenes magic on the back end, so for proper syntax you only need to reference the name of the function you are calling. Map the associated attributes with the appropriate variables in your wrapper class, and add an outputPanel around the chart for advanced rendering.

In order to rerender this chart, I created an actionFunction that gets called onChange of the list value. I had to do this because there is no reRender attribute on the selectList tag, but the actionFunction action is a simple method in my class (public PageReference NoOp()) that does nothing except return null. When the NoOp method finishes, the chart will rerender and call the JavaScript function again using the new value in the list to sort the chart points.

Try it yourself!

Visualforce charting enables you to quickly generate rich, animated charts, without having to use a 3rd party system for the meat of it. There are definitely some kinks in the process right now being that it just went GA in Winter ’13, but I’m sure we’ll be seeing updates and enhancements with upcoming releases in the future.

I have done a few examples here, and there are more examples elsewhere on developer.force.com, but there’s no better way to learn than to try it out yourself. In addition to the examples I have put here, I have also uploaded a full sample pack on GitHub including a complete Apex controller and Visualforce page for each chart type. Take a look at those examples, and feel free to reach out to me via twitter if you have any questions.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS