0

Can someone suggest me to create a Donut chart in the lightning component? Here in a custom object, I have a field having values that are like 1 to 100 %. Based on the percentage I want to show in chart form. Can you help with any examples or suggestions?

In the controller, I am trying to do database.query, which it fetching account 2 fields. But when i tried to fetch those fields value am getting null value.

 @AuraEnabled
public static Integer computePercentage(String sObjectName, String recordId, String totalValueFieldName, String actualValueFieldName){
    Integer retVal = 0 ;
    String query = null;

    if(totalValueFieldName != null && totalValueFieldName.trim() != '' &&  actualValueFieldName != null && actualValueFieldName.trim() != '' ){
        query = 'SELECT '+totalValueFieldName+', '+actualValueFieldName+' FROM '+sObjectName+' WHERE Customer_ID__c = \'' +recordId+ '\'';
        system.debug('First query 36 --- '+query);
    }

    if(query != null){
        system.debug('query -- 44 '+query);
        try{
            List<SObject> lstObj = Database.query(query);
            system.debug('lstObj -- '+lstObj);
            if(lstObj.size() > 0){
                Decimal totalVal = 0;
                Decimal actualVal = 0; 

                if(totalValueFieldName != null && totalValueFieldName.trim() != ''){ 
                    system.debug('totalValueFieldName top -- '+totalValueFieldName);
                    system.debug('lstObj[0].get  totalValueFieldName top -- '+lstObj[0].get(totalValueFieldName));
                    totalVal = Decimal.valueOf(String.valueOf(lstObj[0].get(totalValueFieldName)));

                } 
                actualVal = Decimal.valueOf(String.valueOf(lstObj[0].get(actualValueFieldName)));                     
                //Means only 1 API Name was supplied and field type is percentage
                if(totalVal == 0){
                    retVal = Integer.valueOf(actualVal );
                }else if (actualVal > 0){
                    retVal = Integer.valueOf( ( actualVal / totalVal ) * 100 );  
                } 
            }
        }catch(Exception e){
            system.debug('Exception caused--- '+e+ 'Line number -- '+e.getLineNumber());
        }

    }         
    return retVal;        
}[![enter image description here][1]][1]

Thank you.

enter image description here

2

There are several ways for you to accomplish this. One option will be to get a chart.js and add it to your static resources. I have a few and you could start with this one Chart.js

Get this one:

enter image description here

On your org go to Static Resources and insert the js. Set up -> Custom Code -> Static Resources -> New

Name: Chartjs

Choose the js file that we downloaded from the link above and save the new static resource.

We have the basic chart js that we can import and use in our component.

This is an example that can get you started:

Apex Controller:

public class GraphController {

@AuraEnabled
public List<LineChartVar> myLineChartVarList;

public class LineChartVar {
    String label;
    Integer firstValue;
    Integer secondValue;

    public LineChartVar(String a, Integer b, Integer c) {
        label = a;
        firstValue = b;
        secondValue = c;
    }
}

@AuraEnabled
public static Map<String, Integer> getChartMap() {
    Map<String, Integer> mp = new Map<String, Integer>();
    mp.put('Jan', 45);
    mp.put('Feb', 50);
    mp.put('Mar', 30);
    mp.put('Apr', 36);
    mp.put('May', 42);
    mp.put('Jun', 39);
    mp.put('Jul', 41);
    mp.put('Aug', 36);
    mp.put('Sep', 43);
    mp.put('Oct', 45);
    mp.put('Nov', 33);
    mp.put('Dec', 53);

    return mp;
}

@AuraEnabled
public static String getLineChartMap() {
    List<LineChartVar> myLineChartVarList = new List<LineChartVar>();

    myLineChartVarList.add(new LineChartVar('2010', 10, 12));
    myLineChartVarList.add(new LineChartVar('2011', 12, 15));
    myLineChartVarList.add(new LineChartVar('2012', 17, 19));
    myLineChartVarList.add(new LineChartVar('2013', 19, 17));
    myLineChartVarList.add(new LineChartVar('2014', 21, 15));
    myLineChartVarList.add(new LineChartVar('2015', 17, 20));
    myLineChartVarList.add(new LineChartVar('2016', 18, 16));
    return JSON.serialize(myLineChartVarList);
  }
}

Component

    <aura:component description="DataVisualization" controller="GraphController"
                implements="flexipage:availableForAllPageTypes" access="global">
  <div class="slds-box slds-theme--default">
    <ltng:require scripts="{!$Resource.Chartjs}" afterScriptsLoaded="{!c.ctr}"/>

    <div class="slds-col slds-size--1-of-1 slds-small-size--1-of-2 slds-medium-size--3-of-4">
      <canvas aura:id="barChart" id="barChart"/>
    </div>
    <div class="slds-col slds-size--1-of-1 slds-small-size--1-of-2 slds-medium-size--3-of-4">
      <canvas aura:id="lineChart" id="lineChart"/>
    </div>
  </div>
</aura:component>

Component Controller

 ({
  ctr : function(cmp, event, helper) {
    var temp = [];
    var temp2 = [];
    var action1 = cmp.get("c.getLineChartMap");
    var action = cmp.get("c.getChartMap");
    action.setCallback(this, function(response){
      if(response.getState() === 'SUCCESS' && response.getReturnValue()){
        temp = response.getReturnValue();
        helper.createGraph(cmp, temp);
      }
    });
    action1.setCallback(this, function(response){
      if(response.getState() === 'SUCCESS' && response.getReturnValue()){
        temp2 = JSON.parse(response.getReturnValue());
        helper.createLineGraph(cmp, temp2);
      }
    });
    $A.enqueueAction(action);
    $A.enqueueAction(action1);
  }
});

Helper

    ({
  createGraph : function(cmp, temp) {

    var dataMap = {"chartLabels": Object.keys(temp),
      "chartData": Object.values(temp)
    };

    var el = cmp.find('barChart').getElement();
    var ctx = el.getContext('2d');

    new Chart(ctx, {
      type: 'bar',
      data: {
        labels: dataMap.chartLabels,
        datasets: [
          {
            label: "Payments History",
            backgroundColor: "rgba(153,255,51,0.5)",
            data: dataMap.chartData
          }
        ]
      }
    });
  },
  createLineGraph : function(cmp, temp) {

    var label = [];
    var firstValue = [];
    var secondValue = [];

    for(var a=0; a< temp.length; a++){
      console.debug(temp[a]["label"]);
      label.push(temp[a]["label"]);
      firstValue.push(temp[a]["firstValue"]);
      secondValue.push(temp[a]["secondValue"]);
    }
    var el = cmp.find('lineChart').getElement();
    var ctx = el.getContext('2d');

    new Chart(ctx, {
      type: 'line',
      data: {
        labels: label,
        datasets: [{
          label: 'USD Sent',
          data: firstValue,
          backgroundColor: "rgba(153,255,51,0.4)"
        }, {
          label: 'USD Recieved',
          data: secondValue,
          backgroundColor: "rgba(255,153,0,0.4)"
        }]
      }
    });

    }

   });

If you add you component to a page you will see something like this:

enter image description here

If you go to the Helper and change the first type bar:

type: 'bar' to type: 'doughnut' and after saving you check again you get this:

enter image description here

So as you can see you can play around and make the changes you want. The Apex controller can be also modified to suit your needs.

Check this site as well.

| improve this answer | |
1

If it's just one percentage (or perhaps even one per field), you could build one without any external libraries. Here's an example:


progressShow.cmp

<aura:component implements="force:hasRecordId,flexipage:availableForRecordHome">
    <aura:attribute name="apiField" type="String" default="Id" access="global" />

    <aura:attribute name="record" type="Map" access="private" />
    <aura:attribute name="fields" type="List" access="private" default="['Id']" />
    <aura:attribute name="progressValue" type="Integer" access="private" />
    <aura:attribute name="chartAvailable" type="Boolean" access="private" default="{!false}" />

    <aura:handler name="init" value="{!this}" action="{!c.init}" />

    <force:recordData recordId="{!v.recordId}" fields="{!v.fields}" targetFields="{!v.record}" recordUpdated="{!c.showChart}" />

    <aura:if isTrue="{!v.chartAvailable}">
        <lightning:progressRing value="{!v.progressValue}" />
        <aura:set attribute="else">
            <lightning:spinner />
        </aura:set>
    </aura:if>

</aura:component>   

progressShowController.js

({
    init: function(component, event, helper) {
        component.set("v.fields", [component.get("v.apiField")]);
    },
    showChart: function(component, event, helper) {
        component.set("v.progressValue", 
            component.get("v.record")[component.get("v.apiField")]);
        component.set("v.chartAvailable", true);
    }
})

progressShow.design

<design:component >
    <design:attribute name="apiField" label="Field Name" description="The API Name of the field to display." />
</design:component>

You could add extra features to make it larger/smaller, change the order of the ring, add multiple fields, or almost anything else you can imagine. You can then add this to your record page for any object using the Lightning App Builder.

Feel free to check out the documentation for more information.

| improve this answer | |
  • Thank you @sfdcfox and Carlos Naranjo for your inputs. It helped a lot in working with charts. Here I am using the another functionality. There am getting the error for fetching account field from database.query(query) result. Can you suggest me what is the issue. – Aryan Feb 28 at 20:00
  • @Aryan I would need more info to tell you more. – sfdcfox Feb 28 at 20:08
  • i just updated the issue. Can you check once. – Aryan Feb 28 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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