Click here to Skip to main content
Click here to Skip to main content

Chart SharePoint Hosted App with AngularJs and JqPlot

, 17 Apr 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Building charting Sharepoint hosted app with AngularJs and JqPlot

Introduction

SharePoint 2013 introduced Apps and one of the options is to create SharePoint Hosted Apps, apps that are hosted inside SharePoint in its own app web. With SharePoint hosted apps you can’t use server side code so you are limited to JavaScript. However you can read and write data from SharePoint lists in host web (SharePoint web that is hosting app).

JavaScript frameworks such as Angular, Backbone and Knockout have been matured and became pretty strong.

So, scenario here is to have data inside SharePoint List (custom list, one column for title and one column for value), to create an app with read permissions to access that data, to use angular (http://angularjs.org) for data-binding part and jqPlot (http://www.jqplot.com ) for chart rendering. Also, one chart in this example is using ui-chart directive (http://angular-ui.github.io/ui-chart/), the directive that lets you use jqPlot with Angular.

I’m going to assume that who is interested in this article is having some knowledge about SharePoint 2013, JavaScript and html, so I’m not going to write here about SharePoint apps, AngularJs and jqPlot. You can visit their respective websites in order to learn more about them.

Background

The basic idea for writing this article was to create better charting for SharePoint. In Version 2010 we had chart web part which was OK, in version 2013 this web part is deprecated. Excel is desired solution for charting in SharePoint. It is a power tool but it doesn't cover every scenario especially for quick charts we want to display in our pages.

Introducing the better client scripting support (JSOM, REST) and the app model, Microsoft opened the doors to the whole new world of developing for SharePoint. Now it is possible to develop a solutions, using powerful and proved JavaScript frameworks such as AngularJs and jqPlot.

I've got an idea of creating this app, watching Jeremy Thake's session "SharePoint 2013 Apps with AngularJS", from Las Vegas on channel 9 (http://channel9.msdn.com/Events/SharePoint-Conference/2014/SPC408). Much of the code that is shown here (service that retrieves sharepoint data) is his.

Creating the app

Data

I've made simple custom list in SharePoint called PieChartData. Besides Title column which is auto generated (and I’m going to use it for labels), I added one more column called Value (type - number).

I've also saved this list as template (with data included) and you can download it here - Download PieChartData.zip

You should create this list in the SharePoint web site where your app will be installed.

You can see list with sample data on the image above.

Remark: If you are creating this list by your own, it is very important that internal names of your fields are Title and Value or the code will fail. If you are not able to name your fields like that, or you insist to name it differently, you should also change the code in App.js that retrieves the data from SharePoint. Just find these two lines and change:

var Title = currentItem.get_item("Title"); 
var Value = currentItem.get_item("Value");  

Also if you want to change list name you should change it here (App.js):

var promise = $SharePointJSOMService.getData($scope, 'PieChartData'); 

Second argument is list name.

Idea: It would be nice to create app part and to have property for list name. That would empower your users and give them possibility to change data source.

Sharepoint App Creation

I was using Visual Studio 2013 for this part. I've created new project (image below), App for SharePoint 2013.

Then I selected that it’s going to be SharePoint hosted app (image below).

Last thing was to set permissions for our app. In the Application.manifest file (double click it), under permissions tab just add Read permission for Web object (image below).

And I was ready to go.

Resources

I copied angular.js into Scripts/lib/angular directory of my project, jqplot into Scripts/lib/jqplot, bootstrap into Scripts/lib/bootstrap (but I didn’t even use it). UI-charts chart.js file was copied directly into Scripts/lib directory.

View template

Inside Pages/Default.aspx file which is home page of our app web I referenced required resources and I added view part of our angular app.

This block of includes goes to head part of the Default.aspx page:

<script type="text/javascript" src="../Scripts/lib/angular/angular.js"></script>
<script type="text/javascript" src="../Scripts/lib/jqplot/jquery.jqplot.js"></script>
<script type="text/javascript" src="../Scripts/lib/jqplot/plugins/jqplot.pieRenderer.js">
</script>
<script type="text/javascript" src="../Scripts/lib/jqplot/plugins/jqplot.barRenderer.min.js"></script>
<script   type="text/javascript" src="../Scripts/lib/jqplot/plugins/jqplot.categoryAxisRenderer.min.js"></script>
<script  type="text/javascript" src="../Scripts/lib/jqplot/plugins/jqplot.pointLabels.min.js"></script>
<script type="text/javascript" src="../Scripts/lib/chart.js"></script>
<script type="text/javascript" src="../Scripts/Common.js"></script>
<link rel="stylesheet" type="text/css" href="../Scripts/lib/jqplot/jquery.jqplot.css"/>

And angular view is going to the body:

<div ng-app="myChartingApp" ng-controller="DemoCtrl">
        <div ui-chart="someData" chart-options="myChartOpts" 
      style="width:600px; height:300px”></div>
        <div id="barchart" style="width:600px; height:300px;"></div>
        <div id="linechart" style="width:600px; height:300px;"></div>
</div> 

It’s not very practical to have ng-app directive in html element in SharePoint master page, so I've put it inside div element in my app Default.aspx page. I've also declared DemoCtrl controller (declared with ng-controller directive) so everything inside this div would be part of angularjs myChartApp and it would use DemoCtrl controller.

Inside this app div there are three more divs (they're acting as placeholders for charts):

1. First one is using ui-chart directive and it is bind to someData property of our controller for chart data, and to myChartOpts property for chart options

2. Second div is container for our bar chart that will be rendered directly not with ui-chart directive

3. Third div is container for our line chart that will be rendered directly not with ui-chart directive

That’s all markup we need for this project to work.

Remark: I've provided two scenarios here for creating the charts: one with the ui-chart directive is nice and clean if you create controller and app part for each chart type (or you group similar ones), the second one with method that uses jqplot directly is good when you create one controller which renders different types of charts and you have a property in your app part where user can choose which chart he wants to render.

Javascript

All our code will be in App.js and Common.js.

I've deleted all sample SharePoint code here and put my own. myChartingApp module, DemoCtrl controller and angular service for retrieving SharePointData were defined here.

Remark: all credits for angular service go to Jeremy Thake, which wrote great article about using Sharepoint and AngularJS (http://www.jeremythake.com/2013/10/sharepoint-hosted-app-with-angularjs-for-mvc-javascript/).

Common.js

This file has only one common method, taken from MSDN examples (you can find it in almost every SharePoint hosted app example), that parses QueryString.

function getQueryStringParameter(paramToRetrieve) {
  var params =document.URL.split("?")[1].split("&");
  var strParams = "";
  for (var i = 0; i < params.length; i = i + 1) {
      var singleParam = params[i].split("=");
    if (singleParam[0] == paramToRetrieve)return singleParam[1];
  }
} 

Module

Here is code which defines angular module and injects chart options for pie chart:

var myChartingApp = angular.module('myChartingApp', ['ui.chart'])      
    .value('charting', {       
    pieChartOptions: {              
        seriesDefaults: {                  
            renderer: jQuery.jqplot.PieRenderer,                  
            rendererOptions: {                      
                showDataLabels: true                  
            }              
        },              
        legend: { show: true, location: 'e' }          
    }      
});  

In this code we create myChartingApp, with chart options for creating a pie chart (the one that is using ui-chart directive). We also tell angular that we are going to use ui-chart (['ui.chart'])).

Controller

myChartingApp.controller('DemoCtrl', function ($scope, charting, $SharePointJSOMService) {

Properties
    $scope.someData = [[]];
    $scope.ticks = [];    
    $scope.barvalues = [];
    var promise = $SharePointJSOMService.getData($scope, 'PieChartData');    
    promise.then(function (message) {            
         alert(message);        
    },function (reason) {            
          alert(reason);        
      }          
    );    
    $scope.myChartOpts =charting.pieChartOptions;
… 

Little bit about properties:

  • someData – property that will hold data (collection of title, value pairs from SP list)
  • ticks property – array of ticks (collection of titles from SP list in this example), used in bar chart
  • barvalues – array of values from SP list, used in bar chart for values and line chart for y axis
  • myChartOpts – pie chart options injected into controller. Used in pie chart with ui-chart directive.

Methods

    $scope.setBarChart = function () {
    var plot2 = $.jqplot('barchart', [$scope.barvalues], {            
        seriesDefaults: {                
            renderer: $.jqplot.BarRenderer,                
            pointLabels: { show: true, location: 'e', edgeTolerance: -15 },            
    },            
        axes: {                
            xaxis: {                    
                renderer:$.jqplot.CategoryAxisRenderer,                                            ticks: $scope.ticks                
            }            
        }        
    });    
   } 

Method setbarChart is used for rendering bar chart with jqplot, without help of ui-chart directive. It is very simple, it sets $scope.barvalues as data , $scope.ticks as ticks and it has an option for displaying point labels (pointLabels).

    $scope.setLineChart = function () {    
    var plot = $.jqplot('linechart', [$scope.barvalues], {
                title: 'Sales 2014',            
        axesDefaults: {                
            labelRenderer:$.jqplot.CanvasAxisLabelRenderer            
        }, 
        seriesDefaults: {                
            rendererOptions: {                    
                smooth: true                
            }            
        },            
        axes: {                
            yaxis: {                    
                label: 'Sales', min: 0                
            },                
            xaxis: {                    
                label: 'Months', min: 1, max:$scope.barvalues.length
        }            
        },            
        series: [{ color: '#5FAB78' }]        
    }); 

Method setLineChart is used for rendering line chart with jqPlot, without help of ui-chart directive. It is very simple, it sets $scope.barvalues as y axis data, 1 as minimum for x axis, $scope.barvalues.length as maximum for x axis and it has an option for displaying labels for title, y axis and x axis.

Service

As I said this service has been taken from Jeremy Thake’s blog, with small modifications. Its purpose is to connect to Sharepoint host web and to read data from PieChartData list.

I've added this code inside list enumerator:

var Title = currentItem.get_item("Title");
var Value = currentItem.get_item("Value");
var b = [Title, Value];
$scope.someData[0].push(b);
$scope.ticks.push(Title);
$scope.barvalues.push(Value);

It’s pretty simple, I’m reading Title and Value field values
and add them as collection members to my properties (someData, ticks, barvalues).

Also, outside of the enumerator I'm calling my methods for rendering jqPlot charts:

$scope.setBarChart();$scope.setLineChart(); 

That’s it.

Here is the result (image below):

Conclusion

This is pretty simple app, it's been more a teaser than real app, but this way you could easily catch up with basics of charting with angular in SharePoint apps.

Next steps and ideas:

  • Create app parts with single chart in it, so someone could display charts inside SharePoint pages.
  • Create controllers for different types of charts
  • Try more complex charts

SharePoint Store

If you plan to deploy this kind of apps to SharePoint store you should know that your app should work on IE8. I didn't test angularjs and jqplot against IE8.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Drasko Popovic
Web Developer CPU
Serbia Serbia
No Biography provided

Comments and Discussions

 
QuestionNot able to run the app PinmemberMattias Palm5-Oct-14 22:06 
GeneralThanks Pinmembermilosrak23-Apr-14 8:00 
QuestionGet Current User PinmemberJonathan Gravois21-Apr-14 10:54 
AnswerRe: Get Current User PinmemberDrasko Popovic22-Apr-14 0:13 
Questioncontrollers.js and services.js PinmemberJonathan Gravois19-Apr-14 11:53 
AnswerRe: controllers.js and services.js PinmemberDrasko Popovic19-Apr-14 12:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150327.1 | Last Updated 17 Apr 2014
Article Copyright 2014 by Drasko Popovic
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid