When I say dynamic data, I mean data extracted from an SQL Server database. An Asp.Net Web API controller would provide the data to my AngularJS app. Along with it, I will use $http to call the API, extract data and use the data for my chart.
The Asp.Net Web API controller and model are written in C# and Vb.
Before you start designing your application, you must first download Charts.js and Angular Chart from Github.
You can either download chart.js library or use the Chart.js CDN in your application.
Note: I am using Chart.js CDN in the example, here in this post.
Next, you will also need to download angular-chart.js file in your machine. Save the file the root directory of your application.
Since I am extracting data from SQL Server database, I will need a table. The table dbo.Books_Annual_Sales has two columns, Month and SalesFigure. A bar chart that I am drawing here, has two sides. See the image above. The bars are the SalesFigure for each month.
CREATE TABLE [dbo].[Books_Annual_Sales]( [Month] [varchar](50) NULL, [SalesFigure] [int] NULL ) ON [PRIMARY]
After you have created the table, just add for each month with a sales figure starting from Jan. For example,
INSERT INTO dbo.Books_Annual_Sales VALUES ('JAN', 21) INSERT INTO dbo.Books_Annual_Sales VALUES ('FEB', 56)
and so on.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.http; using System.Web.http; using BooksApp.Models; using System.Data.SqlClient; namespace BooksApp.Controllers { public class BooksController : ApiController { // LIST OBJECT WILL HOLD AND RETURN A LIST OF MONTHLY SALES. List<Books> MyBooks = new List<Books>(); public IEnumerable<Books> Get() { string sConnString = "Data Source=DNA;Persist Security Info=False;" + "Initial Catalog=DNA_Classified;User Id=sa;Password=demo;Connect Timeout=30;"; SqlConnection myConn = new SqlConnection(sConnString); // THE SQL QUERY TO GET THE SALES FIGURES FROM THE TABLE. SqlCommand objComm = new SqlCommand("SELECT *FROM dbo.Books_Annual_Sales", myConn); myConn.Open(); SqlDataReader reader = objComm.ExecuteReader(); // POPULATE THE LIST WITH DATA. while (reader.Read()) { MyBooks.Add(new Books { Month = reader["Month"].ToString(), SalesFigure = reader["SalesFigure"].ToString()}); } myConn.Close(); return MyBooks; } } }>
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace BooksApp.Models { public class Books { public string Month { get; set; } public string SalesFigure { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web.http; namespace BooksApp { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/" ); } } }
Option Explicit On Imports System.Net.http Imports System.Web.http Imports System.Data.SqlClient Imports BooksApp.BooksApp.Models Namespace BooksApp Public Class BooksController Inherits ApiController ' LIST OBJECT WILL HOLD AND RETURN A LIST OF MONTHLY SALES. Dim MyBooks As New List(Of Books)() Public Function [Get]() As IEnumerable(Of Books) Dim sConnString As String = "Data Source=DNA;Persist Security Info=False;" & _ "Initial Catalog=DNA_Classified;User Id=sa;Password=demo;Connect Timeout=30;" Dim myConn As New SqlConnection(sConnString) ' THE SQL QUERY TO GET THE SALES FIGURES FROM THE TABLE. Dim objComm As New SqlCommand("SELECT *FROM dbo.Books_Annual_Sales", myConn) myConn.Open() Dim reader As SqlDataReader = objComm.ExecuteReader() ' POPULATE THE LIST WITH DATA. While reader.Read() MyBooks.Add(New Books() With { _ .Month = reader("Month").ToString(), _ .SalesFigure = reader("SalesFigure").ToString() _ }) End While myConn.Close() Return MyBooks ' FINALLY, RETURN THE LIST. End Function End Class End Namespace
Imports System.Web Namespace BooksApp.Models Public Class Books Public Property Month() As String Get Return m_Month End Get Set(value As String) m_Month = value End Set End Property Private m_Month As String Public Property SalesFigure() As String Get Return m_SalesFigure End Get Set(value As String) m_SalesFigure = value End Set End Property Private m_SalesFigure As String End Class End Namespace
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Web.http Public Class WebApiConfig Public Shared Sub Register(ByVal config As HttpConfiguration) config.Routes.MapHttpRoute( _ name:="DefaultApi", _ routeTemplate:="api/{controller}/" _ ) End Sub End Class
In the markup section, I have included 3 CDN’s. That is, AngularJS, jQuery and the CDN for Chart.js. The forth <script> is the angular-chart.js, which I have saved in the root directory of my application.
<!DOCTYPE html> <html> <head> <title>Drawing Charts in AngularJS</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.1.1/Chart.min.js"></script> <script src="angular-chart.js"></script> </head> <body> <div ng-app="myChart" ng-controller="myController" style="width:700px;"> <p><button ng-click="requestData()">Show Chart</button></p> <canvas id="bar" class="chart chart-bar" data="data" labels="labels" colours="colors"> </canvas> </div> </body>
If you have noticed, I have a button control that will call a function in the controller to request data from the API using $http.
I have included the HTML5 <canvas> element with few directives and a class.
<script> var myApp = angular.module('myChart', ["chart.js"]); myApp.controller( 'myController', function ($scope, $http) { $scope.requestData = function () { var arrData = new Array(); var arrLabels = new Array(); $http.get("/api/books/").success(function (data) { $.map(data, function (item) { arrData.push(item.SalesFigure); arrLabels.push(item.Month.split(',')); }); $scope.data = []; $scope.labels = []; $scope.data.push(arrData.slice(0)); for (var i = 0; i < arrLabels.length; i++) { $scope.labels.push(arrLabels[i]); } }).error(function (status) { alert(status); }); }; // NOW, ADD COLOURS TO THE BARS. $scope.colors = [ { fillColor: 'rgba(161, 75, 201, 0.8)', strokeColor: 'rgba(161, 75, 201, 0.8)', highlightFill: 'rgba(161, 75, 201, 0.8)', highlightStroke: 'rgba(161, 75, 201, 0.8)' } ]; }); </script> </html>
First, I’ll add the chart.js dependency to my module.
var myApp = angular.module('myChart', ["chart.js"]);
Inside the controller, I have a function requestData(), which I’ll call using the button (click). The function has $http to request data from the Web API. Once it successfully extracts data from the API, I’ll first add it in two Arrays, that is, arrData and arrLabels.
The arrays now hold the data for the chart. In the markup section, the HTML5 canvas has three directives namely, data, labels and colours. The first two directives will get data from the two arrays.
The data directive will have the Sale Figures and labels directive will have months. The 3rd directive colours will have color properties for the bars. I am assigning values to the properties at the end.
$scope.colors = [ { fillColor: 'rgba(161, 75, 201, 0.8)', strokeColor: 'rgba(161, 75, 201, 0.8)', highlightFill: 'rgba(161, 75, 201, 0.8)', highlightStroke: 'rgba(161, 75, 201, 0.8)' } ];
Well, that’s it. If everything goes well, you will see an animated chart on your web page, with the click of a button. The good thing is that data is dynamic.