5

I have a batch job that runs twice a month to calculate a score. I dump the data into a custom object called CA_NPS_Score__c. Each record just contains A few decimal fields, and a formula field that calculates the NPS Score. I have to do this in a batch job because the calculations done to get the decimal fields are too complex to do in a formula field.

I was fairly easily able to plot these scores into line graphs using VF charting to show the changes over time. Now my clients would like to have a simple gauge to show the score. These seem simple enough as well, but I am unable to get the gauge to look similar to the normal dashboard gauge. The gauge I created looks similar to the the gauge in this blog post

http://blogs.developerforce.com/developer-relations/2012/10/animated-visualforce-charts.html

The issue is I would like it to look more like the standard gauge dashboard component, mainly to be able to have 2 breakpoints, so I can show my low, medium, and high ranges graphically within the gauge. I have tried overlaying a second and third gauge on top of the gauge to show the different sections. I tried carrying the values of the breakpoints in the wrapper class, but I don't know how to show them visually on the VF page. There doesn't seem to be a way to show anything but the actual value on the gauge.

Is this possible?? Is there another way to accomplish this? I can't imagine I am the only person that has ever needed to create a gauge with breakpoints using VF. I can't help but thinking I am missing something very obvious and easy. Has anyone accomplished this?

Here is a very simple page and controller below:

VF

<apex:page controller="TestPageController">

<script>
    MyChart1.on('beforeconfig', function(config) {
        config.axes[0].margin=-10;
    });
</script>

   <apex:chart name="MyChart1" height="300" width="450" animate="true" data="{!data}">
       <apex:axis type="Gauge" position="gauge" title="Total NPS Score"  minimum="0" maximum="45" steps="10"/>
       <apex:gaugeSeries dataField="score" donut="50" colorSet="#00F,#0F0" needle="true"/>       
   </apex:chart>   
</apex:page>

Controller

public class TestPageController {   

    public TestPageController(){

    }

    public List<gaugeData> getData() {
        double NPS_score = 0;
        CA_NPS_Score__c score = [Select Id, Name, Total_NPS_Score__c, Most_Current__c  From CA_NPS_Score__c Where Most_Current__c = true];

        List<gaugeData> data = new List<gaugeData>();
        data.add(new gaugeData('NPS', score.Total_NPS_Score__c));
        return data;
    }
    public class gaugeData {
        public String name { get; set; }
        public decimal score { get; set; }
        public decimal lowRange { get; set; }
        public decimal highRange { get; set; }

        public gaugeData(String name, decimal npsScore) {
            this.name = name;
            this.lowRange = 17;
            this.highRange = 30;
            this.score = npsScore;
        }
    }
}

Here are some Visuals of what I am talking about: enter image description here

enter image description here

2
  • 2
    Have you looked into HTML5/Javascript gauges? There are many options, both free and commercial, that would get you much closer than VF charting.
    – Hraefn
    Commented Aug 26, 2013 at 16:46
  • I haven't. I was really hoping to stick with just Vf and Apex. I can look into that if that my only options, but wanted to check. Commented Aug 26, 2013 at 16:51

1 Answer 1

3

I actually had to take Hraefn's advice. I went with jQuery to accomplish this as opposed to visualforce charting. I used a nice jQuery library chartJs, which can be found here

http://chartjs.devexpress.com/

Here is the basic code I used. Someone could easily adjust this to fit there data

VF

<apex:page controller="NPSScoreController">

    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.10.2.custom/js/jquery-1.9.1.js')}" />    
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.10.2.custom/js/jquery-ui-1.10.2.custom.min.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.10.2.custom/js/d3.v3.js')}" />
    <apex:styleSheet value="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/smoothness/jquery-ui.css" />
    <apex:includeScript value="{!URLFOR($Resource.ChartJs, 'Lib/js/knockout-2.2.1.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.ChartJs, 'Lib/js/globalize.min.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.ChartJs, 'Lib/js/dx.chartjs.js')}" />



    <script>
    var j$ = jQuery.noConflict();

    //On Page load
    j$(function() {

        createBullet('OverallContainer', 'Total NPS Score', '{!score.Total_NPS_Score__c}');
        createBullet('EpicContainer', 'Epic Score', '{!score.Epic_NPS_Score__c}');
        createBullet('CernerContainer', 'Cerner Score', '{!score.Cerner_NPS_Score__c}');
        createBullet('RemContainer', 'Remediation Score', '{!score.Remediation_NPS_Score__c}');
        createBullet('DeployedContainer', 'Deployed Score', '{!score.Deployed_NPS_Score__c}');
        createBullet('LargestContainer', 'Largest Score', '{!score.Largest_NPS_Score__c}');
        createBullet('TierBContainer', 'Tier B Score', '{!score.TIER_B_NPS_Score__c}');
        createBullet('NewTierBContainer', '2013 New Tier B Score', '{!score.New_Tier_B_NPS_Score__c}');
        createBullet('NewTierAContainer', '2013 New Tier A Score', '{!score.New_Tier_A_NPS_Score__c}');
        createBullet('EMEARemediationContainer', 'EMEA Remediation Score', '{!score.EMEA_Remediation_NPS_Score__c}');
        createBullet('EMEADeploymentContainer', 'EMEA Deployment Score', '{!score.EMEA_Deployment_NPS_Score__c}');

    });

    function createBullet(divId, title, nps){
        j$("#" + divId).dxLinearGauge({
            scale: {
                startValue: -20,
                endValue: 50,
                label: {
                    indentFromTick: 7
                },
                majorTick: {
                    showCalculatedTicks: false,
                    customTickValues: [0, 17, 30, 50],
                    color: "#000"           
                }
            },

            title: {
                text: title,
                font: {
                    color:'#000',
                    weight:900,
                    size: 20
                }
            },

            rangeContainer: {
                backgroundColor: "none",
                ranges: [
                    {
                        startValue: -20,
                        endValue: 17,
                        color: "red"
                    },
                    {
                        startValue: 17,
                        endValue: 30,
                        color: "orange"
                    },
                    {
                        startValue: 30,
                        endValue: 50,
                        color: "green"
                    }
                ]
            },

            //needles: [{ value: nps, color: "#000"}],      
            markers: [{ value: nps, color: "#000"}],        

        });
    }

    </script> 
        <div class="Page-Wrap">
            <div class="First-Line">
                <div id="OverallContainer" class="Container"></div> 
            </div>
            <div class="Lower-Line">
                <div class="Lower-Left">
                    <div class="Container-Wrapper">
                        <div id="EpicContainer" class="Container"></div> 
                    </div>
                    <div class="Container-Wrapper">
                        <div id="CernerContainer" class="Container"></div> 
                    </div>
                    <div class="Container-Wrapper">
                        <div id="RemContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="NewTierAContainer" class="Container"></div>
                    </div>  
                    <div class="Container-Wrapper">
                        <div id="NewTierBContainer" class="Container"></div>
                    </div>
                </div>  

                <div class="Lower-Right">
                    <div class="Container-Wrapper">
                        <div id="DeployedContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="LargestContainer" class="Container"></div>
                    </div>  
                    <div class="Container-Wrapper">
                        <div id="TierBContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="EMEARemediationContainer" class="Container"></div>
                    </div>
                    <div class="Container-Wrapper">
                        <div id="EMEADeploymentContainer" class="Container"></div>
                    </div>      
                </div>      
            </div>   
        </div>

    </apex:page>

Controller

public class NPSScoreController {

    public CA_NPS_Score__c score                        {get;set;}

    public NPSScoreController(){
        score = getScore();
    }

    public List<Schema.FieldSetMember> getFields() {
        return SObjectType.CA_NPS_Score__c.FieldSets.Dashboard_Fields.getFields();
    }

    private CA_NPS_Score__c getScore() {
        String query = 'SELECT ';
        for(Schema.FieldSetMember f : SObjectType.CA_NPS_Score__c.FieldSets.Dashboard_Fields.getFields()) {
            query += f.getFieldPath() + ', ';
        }
        query += 'Name FROM CA_NPS_Score__c Where Most_Current__c = true';
        return Database.query(query);
    }
}

And this is what it came out looking like...

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .