Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Objective

I'm trying to create a series of inline charts to be displayed on the detail of a record using either Visualforce Charting or Highcharts. The charts do need to be dynamically rerendered based on any changed information on the page, they are static after page load. I would like to create charts like this for a few different objects in the database so I've setup a controller extension that services muliple sObjects and uses a series of if statements and instanceOf declarations in the constructor to figure out the object I'm on. My goal is write the fewest lines of code using abstract or virtual classes when appropriate and I'm in need of an appropriate design pattern.

Other Requirements

Ideally, my controller could service all of the charts but this is where I got stuck. Each chart has so many different attributes, like type (pie, bar, or multi-axis line and bar), whether there is a right axis, the SOQL query or in some cases multiple SOQL queries for multi-axis charts, and on and on. Since I'm not sure I can fully componentize my chart with passed in attributes given the complexity of each chart, is there anything that can be made extensible in my controller? What is the same from chart to chart is whether or not the org uses the fiscal year, and the data model of the charts. There is always a set of x-axis categories like months or years, and there is always one, two, or three numeric data sets for the y-axis.

In my controller extension, I'm having to write getters for each set of categories and each data set for each chart and I'm thinking that there must be a better, more extensible way. What am I missing?

share|improve this question

3 Answers 3

Can you create Visualforce components for the different chart types (pie, bar, or multi-axis line and bar) and use attributes to control how each chart looks? All of the components would share a controller extension for retrieving data. Some of the component attributes would be common to all components, and dictate what data to pull from the controller extension to feed into the chart.

You should be able to generalize your controller extension to provide different sets of data, in formats that can work in multiple components. Include a method to respond with metadata based on an attribute of the component -- title for graph, labels for axes, etc. Then each component can choose if/how to display that data in the chart it's rendering.

share|improve this answer

I suspect what you may be missing is that you can treat everything as either a generic sObject or as a string, then convert it to the type of sObject that's needed once you know what it is that you need either using casting or other methods. There's an Apex utility class that converts object types into strings which is described (including code) on Sam Arjmandi's blog which might be of use to you. Methods for creating generic sObjects are described in the Apex documentation on the SFDC web site and elsewhere. Hopefully, one of those solutions will get you started in the right direction.

I'll add, that it sounds as though you're going to need to assemble some kind of "string" to create your queries which will be dependent on whether or not that particular sObject is used. If it were me, I'd put them all together into some kind of format that included all of the possibilities. I'd then check for each type as they were passed to the controller. Finally, I'd pass the values into a string to create the query while ignoring any objects that had null values passed-in to your controller. Thus, in my view, the benefits of some kind of string conversion of the values you want to parse.

You may also need to create several different types of queries depending on the type of chart you want to make. Passing the controller booleans or some other variable to tell it the type can be used as a means to determine which query function your controller needs to use.

Those are just a few thoughts that immediately come to mind that I'd hope would help point you in the right direction.

share|improve this answer
    
Thanks for the response. I am using a single controller extension for the campaign, contact, and account objects with sObject casting. I've thought of passing in the query. How would you do this? I could always use a remoting method but then my calls are static and I lose the controller context and variables (for use fiscal year, for example). Definitely an option. Can you think of another way to pass in my SOQL from the page? Component param? –  greenstork Feb 8 '13 at 22:44

I think you're on the right track. I'm not sure if you're going to be able to reduce the complexity of building different queries for different sObjects, so I'm not sure how much code re-use you can get out of the controller. However, I do think you can make the passing of parameters to the page efficient using JS remoting. Similar to crmprogdev's answer in which it was suggested to build a parameter string, I think it might be easier to create a custom Apex wrapper interface that encapsulates all the parameters you need to pass from the page to the controller to create the chart. With JS remoting, you can construct instances of custom Apex interfaces (or classes), and pass them to the @RemoteAction method. Using an interface would promote re-use and loose coupling. Don't know if that helps or not!

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.