Create Dashboards In SharePoint Using ChartJS

Excel Web Part Services have been catering to the dashboard requirements of SharePoint because of their performance, but let’s face it – they are very heavily dependent on various services/features and require quite some effort in customization and configuration.

This is where the fast and responsive ChartJS comes into the picture. In one of my previous articles, I have written about creating easy dashboards in HTML using ChartJS. If you are not familiar with ChartJS, the previously linked article will get you up-to-speed quickly.

Let us create a dashboard for the below list in SharePoint Online.

Create Dashboards In SharePoint Using ChartJS 

This list contains a list of candidate names and their cities. We will create a dashboard out of this data that will display the below charts –

  • A bar graph depicting Number of Persons against each city
  • All other forms of graphs available in ChartJS

The idea is to create a button click event, on click of which, the dashboards will be generated. That data will be queried over from SharePoint list using REST API.

Getting Started

Let us start with a simple skeleton of HTML5. Place just a canvas element with id “myChartContainer”.

Similar to what was explained in the previous article, ChartJS requires jQuery, Bootstrap, and ChartJS libraries. You can link them from CDN in your HTML page –

At this point, we will just create a button, with a function RunChart() and rest of the HTML and the webpage would look like below.

  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge">  
  6.     <title>Chart JS Demo</title>  
  7.     <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>  
  8.     <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script>  
  9.     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />  
  10. </head>  
  11. <body>  
  12. <br> <br>  
  13. <button onclick="RunChart()">Generate Chart</button> <br><br>  
  14.   
  15.     <div style="position: relative; height:800px; width:800px">  
  16.     <canvas id="myChartContainer" style="border:1px solid"></canvas>  
  17.     </div>  
  18.       
  19. </body>  
  20. </html>  

Create Dashboards In SharePoint Using ChartJS

Adding the Rest API Data retrieval functions and ChartJS elements inside your HTML

Our HTML skeleton is ready at this point. Next, let us follow these steps.

  • Write methods to capture the data from the list using the REST API.
  • Pass the data (labels and data in ChartJS basically) to the ChartJS element

This is how the entire code looks. The detailed explanation is presented after the code.

  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge">  
  6.     <title>Chart JS Demo</title>  
  7.     <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>  
  8.     <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"></script>  
  9.     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />  
  10.     <script>  
  11.   
  12.     var AllUniqueCities = [];  
  13.     var AllCandidateCount = [];  
  14.   
  15.     function RunChart()  
  16.     {  
  17.         var cities = [];  
  18.         var candidatepercity = [];  
  19.   
  20.         cities = GetAllCities();  
  21.         candidatepercity = GetCandidatesPerCity(cities);  
  22.   
  23.         var ctx = document.getElementById('myChartContainer').getContext('2d');  
  24.         var myChart = new Chart(ctx, {  
  25.         type:'bar'// bar, horizontalBar, pie , line, doughnut, radar, polarArea  
  26.         data:{  
  27.             labels: cities,  
  28.             datasets:[{  
  29.             label:'Participants vs City',  
  30.             data: candidatepercity,  
  31.             backgroundColor: ['green''red''blue''purple''black'],  
  32.             borderWidth:1,  
  33.             borderColor:'black',  
  34.             hoverBorderWidth:3,  
  35.             hoverBorderColor:'black',  
  36.             }]  
  37.         },  
  38.         options:{  
  39.             title:{  
  40.                 display:true,  
  41.                 text:'Participants vs City',  
  42.                 fontSize:20  
  43.             },  
  44.             scales: {  
  45.                 yAxes: [{  
  46.                     ticks: {  
  47.                         beginAtZero: true    
  48.                     }  
  49.                 }]  
  50.             }  
  51.          }  
  52.         });  
  53.     }  
  54.   
  55.     function GetAllCities(){  
  56.         var myURL = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('Score')/Items?$top=5000&$select=City";  
  57.         var AllCities = [];  
  58.         $.ajax({  
  59.             url: myURL,  
  60.             async: false,  
  61.             method: "GET",  
  62.             headers: { "Accept""application/json; odata=verbose" },  
  63.             success: function (data) {  
  64.                 if (data.d.results.length > 0) {  
  65.                     //alert("success");  
  66.                     AllCities = data.d.results;  
  67.                     for (var i = 0; i < Number(AllCities.length); i++){  
  68.                         AllUniqueCities.push(AllCities[i].City);  
  69.                     }     
  70.                       
  71.                     AllUniqueCities = removeDuplicates(AllUniqueCities);  
  72.                     //alert(AllUniqueCities.join("-"));  
  73.                 }  
  74.         },  
  75.         error: function (error) {  
  76.             alert("Error: " + JSON.stringify(error));  
  77.         }  
  78.     });  
  79.     return AllUniqueCities;  
  80.     }  
  81.   
  82.     function GetCandidatesPerCity(cityArray){  
  83.         var searchText;  
  84.         for (var i = 0; i < cityArray.length; i++)  
  85.             {              
  86.                 searchText = cityArray[i];  
  87.                 var _count  = FetchCityCount(searchText);  
  88.                 AllCandidateCount.push(_count);  
  89.                // alert("For " + searchText + ", count is: " + _count);  
  90.   
  91.             }  
  92.         return AllCandidateCount;  
  93.     }  
  94.   
  95.     function FetchCityCount(searchItem){  
  96.         var myURL = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('Score')/Items?$top=5000&$select=Title&$filter=City eq '"+ searchItem +"'";  
  97.         var myCandidateCount = 0;  
  98.         $.ajax({  
  99.             url: myURL,  
  100.             method: "GET",  
  101.             async: false ,  
  102.             headers: { "Accept""application/json; odata=verbose" },  
  103.             success: function (myData1) {  
  104.                 if (myData1.d.results.length > 0) {  
  105.                     myCandidateCount = myData1.d.results.length;  
  106.                 }  
  107.             },  
  108.             error: function (error) {  
  109.                 alert("Error: " + JSON.stringify(error));  
  110.             }  
  111.         });  
  112.   
  113.         return myCandidateCount;  
  114.     }  
  115.   
  116.     function removeDuplicates(arr){  
  117.     var unique_array = [];  
  118.     for(var i = 0;i < arr.length; i++){  
  119.         if(unique_array.indexOf(arr[i]) == -1){  
  120.             unique_array.push(arr[i])  
  121.             }  
  122.         }  
  123.     return unique_array  
  124.     }  
  125.   
  126.     
  127.     </script>  
  128. </head>  
  129. <body>  
  130.     <br><br>  
  131.     <button onclick="RunChart(); return false;">Generate Chart</button> <br><br>  
  132.           
  133.     <div style="position: relative; height:800px; width:800px;">          
  134.         <canvas id="myChartContainer" style="border:1px solid"></canvas>  
  135.     </div>  
  136.       
  137. </body>  
  138. </html>  

The primary functions are explained below.

RunChart() is the initializing function. First, it calls two other functions,

  • GetAllCities(), that returns the unique cities present in the list,
  • GetCandidatesPerCity() that queries the list for a number of candidates in the list based on the city name passed as a parameter

Please note that the REST Calls are synchronous (async: false). It means that until it gets the data, the function won’t proceed to the next line/function. This has to be done to ensure that the dashboard has data before it's loaded.

And this is how ChartJS is instantiated in your HTML DOM.

  1. var ctx = document.getElementById('myChartContainer').getContext('2d');  
  2. var myChart = new Chart(ctx, { //... the usual chartJS configs...//});  

The labels and data are provided by the previous methods,

  1. data:{  
  2.     labels: cities,  
  3.     datasets:[{  
  4.     data: candidatepercity,  
  5.     //other configs  
  6.     }]  
  7. },  

The code is done now! Click on the button to get the result.

Create Dashboards In SharePoint Using ChartJS 

To get a pie chart, change the type to pieand the dashboard will display as a pie chart now.

Fun fact about Pie charts in ChartJS – click on any of the legends, and see the pie chart’s interactive response with the data,

Create Dashboards In SharePoint Using ChartJS 

A few other visualizations of the same data are as follows,

Type – line

Create Dashboards In SharePoint Using ChartJS 

Type – doughnut

Create Dashboards In SharePoint Using ChartJS 

Type – radar

Create Dashboards In SharePoint Using ChartJS 

Type - polarArea

Create Dashboards In SharePoint Using ChartJS 

The code for this dashboard can also be found in my GitHub repo.

Hope you enjoyed the article. Please leave your thoughts/queries in the comments below.