Opportunity Chart container.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<!--Render the chart only when the opportunity data is available.--> | |
<template if:true={opportunityData}> | |
<!--We need not have another component for chart, | |
I thought it would be a better idea seperate out the charting component | |
for better readability--> | |
<c-opportunity-pie-chart chart-data={opportunityData}></c-opportunity-pie-chart> | |
</template> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LightningElement,api,wire,track } from 'lwc'; | |
import opportunityAggregation from '@salesforce/apex/OpportunityDataService.aggregateOpportunities' | |
export default class OpportunityChartContainer extends LightningElement { | |
@api recordId; //As the component is loaded on a account detail page, we will get access to the account Id. | |
@track opportunityData=[];//Chart accepts data in multiple formats, array, object etc. We are using array here. | |
//get the data from the backend | |
@wire(opportunityAggregation,{accountId : '$recordId'}) opptyData({error, data}){ | |
if(data){ | |
let oppData = Object.assign({},data); | |
/* | |
this.opportunityData will in the below format | |
[['Closed Won',2],['Closed Lost',4],['Negotiation',5]]; | |
*/ | |
for(let key in oppData){ | |
if(oppData.hasOwnProperty(key)){ | |
let tempData=[key, oppData[key]]; | |
this.opportunityData.push(tempData); | |
} | |
} | |
} | |
if(error) | |
console.log(error); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="opportunityChartContainer"> | |
<apiVersion>46.0</apiVersion> | |
<isExposed>true</isExposed> | |
<targets> | |
<target>lightning__RecordPage</target> | |
<target>lightning__AppPage</target> | |
<target>lightning__HomePage</target> | |
</targets> | |
</LightningComponentBundle> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public with sharing class OpportunityDataService { | |
@AuraEnabled(cacheable=true) | |
public static Map<String, Integer> aggregateOpportunities(String accountId){ | |
Map<String, Integer> opportunityStatusMap = new Map<String, Integer>(); | |
//Aggregate the opportunities. | |
for(AggregateResult aggr : [SELECT Count(Id), StageName | |
FROM Opportunity | |
WHERE AccountId=:accountId | |
GROUP BY StageName]) { | |
opportunityStatusMap.put((String)(aggr.get('StageName')), (Integer)(aggr.get('expr0'))); | |
} | |
return opportunityStatusMap; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<lightning-card title="Opportunities"> | |
<!--C3 manipulates the dom and in order for it to do so we need to add the lwc:dom attribute--> | |
<div lwc:dom="manual" class="c3"></div> | |
</lightning-card> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LightningElement, api,track } from 'lwc'; | |
import { loadStyle, loadScript } from 'lightning/platformResourceLoader'; | |
import C3 from '@salesforce/resourceUrl/c3';//load the c3 and d3 from the static resources. | |
import D3 from '@salesforce/resourceUrl/d3'; | |
export default class OpportunityPieChart extends LightningElement { | |
@api chartData; | |
@track chart; | |
@track loadingInitialized=false; | |
librariesLoaded = false; | |
//This is used called when the DOM is rendered. | |
renderedCallback() { | |
if(this.librariesLoaded) | |
this.drawChart(); | |
//this.librariesLoaded = true; | |
if(!this.loadingInitialized) { | |
this.loadingInitialized = true; | |
/* | |
We have added the a parameter t and assigned the current time to it. | |
This is done to make sure the cache is refrehed everytime the scripts are loaded. | |
If we do not do this then there is an issues if we add multiple charts in a single component. | |
*/ | |
Promise.all([ | |
loadScript(this, D3 + '/d3.min.js?t='+new Date().getTime()), | |
loadScript(this, C3 + '/c3-0.7.4/c3.min.js?t='+new Date().getTime()), | |
loadStyle(this, C3 + '/c3-0.7.4/c3.min.css?t='+new Date().getTime()), | |
]) | |
.then(() => { | |
this.librariesLoaded = true; | |
//Call the charting method when all the dependent javascript libraries are loaded. | |
this.drawChart(); | |
}) | |
.catch(error => { | |
console.log('The error ', error); | |
}); | |
} | |
} | |
drawChart() { | |
this.chart = c3.generate({ | |
bindto: this.template.querySelector('div.c3'),//Select the div to which the chart will be bound to. | |
data: { | |
columns: this.chartData, | |
type : 'donut' | |
}, | |
donut : { | |
title : 'Opportunities', | |
label: { | |
format: function(value, ratio, id) { | |
return value; | |
} | |
} | |
} | |
}); | |
} | |
//destroy the chart once the elemnt is destroyed | |
disconnectedCallback() { | |
this.chart.destroy(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment