Thursday, April 14, 2016

Create Graphs and Charts from SharePoint lists using charts.js

Chart.js is an HTML5 responsive library to build beautiful charts.

Now that charts web part is no longer available in SharePoint 2013, I decide to go for this option. We can also use excel services , but I like this better :)


We will be using REST api to pull items from the list and draw out charts
Create a canvas tag
<canvas id="myChart" width="600" height="400"></canvas>
Include  jquery.js , chart.js and underscore.js  and the below script will do the work.

Make sure to change the List name and use internal name for columns instead of display name. Add this to the script editor or content editor web parts . If you are on one site and want to get data from another site you have to modify the code.

var chartX = []; //X-Axis Labels
var chartY = []; //Y-Axis Values

var chartJs = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js";

var chartId = "myChart"; //Chart Canvas Div    
var charts = ["Line", "Bar", "Radar", "Polar Area", "Pie", "Doughnut"];
var colors = ["#009EA0", "#A7A9AC", "#D15F27", "#BAD80A", "#E0AA0F", "#754760", "#373535"]

var listName = "Incoming Requests"; //Data List Name
var xAxisName = "Request_x0020_Category"; //X-Axis Label Names from List
var yAxisName = "Time_x0020_Calc"; //Y-Axis Values from List

//Set chart number to render different charts
// 0 = Line Chart
// 1 = Bar Chart
// 2 = Radar Chart 
// 3 = Polar Area Chart
// 4 = Pie Chart
// 5 = Doughnut Chart    
var chartNumber = 3;
//Set group by boolean to create chart based on count of x Axis 
var boolGroupByXAxis = true;
var numberOfItemsFromList = null; //Limit number of items returned from the list , for unlimited items type null 

$(document).ready(function() {

    console.log(_spPageContextInfo.webAbsoluteUrl);
    var Url = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('" + listName + "')/items"; //
    if (numberOfItemsFromList != null) {
        Url = Url + "?$top=" + numberOfItemsFromList;
    }
    getItems(Url, boolGroupByXAxis, charts[chartNumber]);




});

function getItems(url, groupby, chartType) {
    $.ajax({
        url: url,
        method: 'GET',
        beforeSend: function(XMLHttpRequest) {

            XMLHttpRequest.setRequestHeader("Accept", "application/json; odata=verbose");
        },

        cache: true,
        error: function(data) {},

        success: function(data) {
            if (!groupby) {
                $.each(data.d.results, function(i, item) {
                    chartX.push(item[xAxisName]);
                    chartY.push(item[yAxisName]);
                });
            } else {
                var arrCount = _.countBy(data.d.results, function(obj) {
                    return obj[xAxisName];
                });
                console.log(arrCount);
                chartX = _.keys(arrCount);
                chartY = _.values(arrCount);
            }
            loadJS(chartJs, function() {

                //Generate Data
                var data = [];
                if (chartType == "Line" || chartType == "Bar" || chartType == "Radar") {
                    data = {
                        labels: this.chartX,
                        datasets: [{
                            fillColor: "rgba(0,160,175,0.5)",
                            strokeColor: "rgba(0,160,175,0.8)",
                            highlightFill: "rgba(0,160,175,0.75)",
                            highlightStroke: "rgba(0,160,175,1)",
                            data: this.chartY
                        }]
                    };
                } else if (chartType == "Pie" || chartType == "Doughnut" || chartType == "Polar Area") {
                    $.each(chartX, function(i, item) {
                        data.push({
                            value: chartY[i],
                            color: colors[i],
                            label: item
                        });
                    });
                    console.log(data);

                }

                //Display Chart
                var ctx = document.getElementById(chartId).getContext("2d");
                switch (chartType) {
                    case "Line":
                        var myNewChart = new Chart(ctx).Line(data);
                        break;
                    case "Bar":
                        var myNewChart = new Chart(ctx).Bar(data);
                        break;
                    case "Radar":
                        var myNewChart = new Chart(ctx).Radar(data);
                        break;
                    case "Polar Area":
                        var myNewChart = new Chart(ctx).PolarArea(data);
                        break;
                    case "Pie":
                        var myNewChart = new Chart(ctx).Pie(data);
                        break;
                    case "Doughnut":
                        var myNewChart = new Chart(ctx).Doughnut(data);
                        break;
                    default:
                        var myNewChart = new Chart(ctx).Line(data)
                }

            });
        }
    });
}


function loadJS(src, callback) {
    var s = document.createElement('script');
    s.src = src;
    s.async = true;
    s.onreadystatechange = s.onload = function() {
        var state = s.readyState;
        if (!callback.done && (!state || /loaded|complete/.test(state))) {
            callback.done = true;
            callback();
        }
    };  

Share This!

15 comments:

  1. I'm trying this option as you suggested but it only renders the complete script on the page (used script editor web part here).
    Will it be possible for you to add a complete script here..?

    ReplyDelete
    Replies
    1. If you use a script editor, you will have to include the script tag to wrap your code...

      Delete
  2. Ashutosh,

    Did you receive a reply?

    ReplyDelete
  3. Hi, trying to test this and I get just a box (presumably the 600*400 set by canvas id. I didn't understand the section of the blog

    Include jquery.js , chart.js and underscore.js and the below script will do the work.

    What do I need to do with the above? Have I missed a step. I've checked my list name, used internal field names and put the script in a CEWP....

    ReplyDelete
  4. Can we have multiple charts on the same page. That is we use Both bar and pie charts with 2 web parts only the last one is getting loaded

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Yes, make sure the chartid is different.

      Delete
    3. Even when my chartid is different I still can't display multiple charts, I can see them in edit mode but not in saved. Only the last one is displayed then, any ideas?

      Delete
    4. Try saving ,checking in and publishing your page, if you are not working on production environment.

      Delete
  5. Hi, trying to test this and I get just a box (presumably the 600*400 set by canvas id. I didn't understand the section of the blog

    Include jquery.js , chart.js and underscore.js and the below script will do the work.

    What do I need to do with the above? Have I missed a step. I've checked my list name, used internal field names and put the script in a Script Editor Web Part

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. I added all of the includes to my master page, created a page, added Script Editor, created canvas and added the code inside script tag. Made proper reference to my list. I GET NOTHING DISPLAYED.

    ReplyDelete
  8. Hey Saswati, So happy to come across your blog :) This worked like magic for me ..Thanks :)

    ReplyDelete
  9. How did you make it out?

    I need a step by step more clear, I am not getting any result by copying and pasting the code, even when I have adopted the code to my SP list

    ReplyDelete