How to work with the Ignite UI Chart in an AngularJS application

Dhananjay Kumar / Monday, September 7, 2015

 

 
In this post we will learn how to work with the Ignite UI chart in an AngularJS application. Although I will use the ASP.NET Web API to pull data from the database, you can use REST service or a Web API created on any stack with the Ignite UI charts in your AngularJS application. This article is divided in two sections:

1.       Section 1 : creating ASP.NET Web API using Code First approach

2.       Section 2 :  using Ignite UI in AngularJS application

If you already have or know how to create the Web API REST Service (Note: from here on out in this post, we’ll use the term “Web API” to refer both to REST Service and Web API), you can jump to section 2 of this article. On the other hand if you need help in how to create ASP.NET Web API start from the section 1.  Here’s a high level flow of diagram of an application::
 
 
Section: 1: Creating the ASP.NET Web API
In this section we will learn how to create a Web API using the following steps:

1.       CRUD operations on database using the Entity Framework Code First approach

2.       Expose the CRUD operations as ASP.NET Web API

 
CRUD operations on database using the Code First approach
We will implement the code first approach in two different projects:

1.       Core project

2.       Infrastructure Project

In the core project you should keep the entities and the repositories interfaces. In this example we are going to work with the City entity. So let us create a class called City as shown in the listing below:
 
using System.ComponentModel.DataAnnotations;
 
namespace WebApiRepositoryPatternDemo.Core.Entities
{
   public class City
    {
       public int Id { get; set; }
       [Required]
       public string Name { get; set; }
       public string Country { get; set; }
       public int Population01 { get; set; }
       public int Population05 { get; set; }
       public int Population10 { get; set; }
       public int Population15 { get; set; }
    }
}
 
As you see we are annotating data using the Required attribute which is the part of System.ComponentModel.DataAnnotations. We can put an annotation on the city entity using either of two approaches:

1.       Using the System.ComponentModel.DataAnnotations

2.       Using the Entity Framework Fluent API

Both approaches have their own advantages - if you consider that restriction on the domain entities is part of the domain then use data annotations in the core project. However if you consider restrictions related to the database and prefer using the Entity framework as your database technology then use fluent API.
 
Next let’s go ahead and create the repository interface. Whatever operation you want to perform on the City entity should be part of the repository interface. The ICityRepository interface can be created as shown in the listing below:
 
using System.Collections.Generic;
using WebApiRepositoryPatternDemo.Core.Entities;
 
namespace WebApiRepositoryPatternDemo.Core.Interfaces
{
    public interface ICityRepository
    {
        void Add(City b);
        void Edit(City b);
        void Remove(string Id);
        IEnumerable<City> GetCity();
        City FindById(int Id);
    }
}
 
Keep in mind that the Core project should never contain any code related to database operations. Hence, the following references should not be the part of the core project:

·         Reference to any external library

·         Reference to any database library

·         Reference to any ORM like LINQ to SQL, entity framework etc.

After adding the entity class and the repository interface, the core project should look like this:
 
Next we will create the infrastructure project, where we’ll perform operations which are related to outside the application. For example:

·         Database operations

·         Consuming web services

·         Accessing File systems

To perform the database operation we are going to use the Entity Framework Code First approach. Keep in mind that we have already created the city entity on which CRUD operations are needed to be performed. Essentially to enable CRUD operations, the following classes are required:

·         DataContext class

·         Repository class implementing the repository interface created in the core project

·         DataBaseInitalizer class

We need to add the following references in the infrastructure project:

·         Reference of the Entity framework. To add this, right click on the project and click on manage Nuget package and then install Entity framework.

·         Reference of the core project.

In the DataContext class:

1.       Create a DbSet property which will create the table for City entity

2.       In the constructor of the DataContext class, pass the connection string name where the database would be created

3.       The CityDataContext class will inherit the DbContext class

The CityDataContext class can be created as shown in the listing below:
 
using System.Data.Entity;
using WebApiRepositoryPatternDemo.Core.Entities;
 
namespace WebApiRepositoryPatternDemo.Infrastructure
{
   public class CityDataContext : DbContext
   {
       public CityDataContext() : base("name=cityconnectionstring")
       {
 
       }
       public IDbSet<City> Cities { get; set;  }
 
    }
}
 
Optionally you can pass the connection string or rely on the Entity Framework to create the database. We will set up the connection string in app.config of the infrastructure project. Let’s go ahead and set the connection string as shown in the below listing:
  <connectionStrings>
  <add name="cityconnectionstring" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=CityPolulation;Integrated Security=True;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>
  </connectionStrings>
 
We need to create database initialize class to feed the database with some initial value at the time of creation. To create the Database initialize class, create a class and inherit it from DropCreateDatabaseIfModelChnages. We are setting the value that if the model changes recreate the database. We can explore the other options of the entity framework also and inherit the database initialize class from the cross ponding class.  In the Seed method we can set the initial value for the Cities table. With a record of three cities, the Database initializer class can be created as shown in the listing below:
 
using System.Data.Entity;
using WebApiRepositoryPatternDemo.Core.Entities;
 
namespace WebApiRepositoryPatternDemo.Infrastructure
{
    public class CityDbInitalize : DropCreateDatabaseIfModelChanges<CityDataContext>
    {
 
        protected override void Seed(CityDataContext context)
        {
            context.Cities.Add(
                  new City
                  {
                      Id = 1,
                      Country = "India",
                      Name = "Delhi",
                      Population01 = 20,
                      Population05 = 22,
                      Population10 = 25,
                      Population15 = 30
                  });
 
            context.Cities.Add(
                 new City
                 {
                     Id = 2,
                     Country = "India",
                     Name = "Gurgaon",
                     Population01 = 10,
                     Population05 = 18,
                     Population10 = 20,
                     Population15 = 22
                 });
                
            context.Cities.Add(
                 new City
                 {
                     Id = 3,
                     Country = "India",
                     Name = "Bangalore",
                     Population01 = 8,
                     Population05 = 20,
                     Population10 = 25,
                     Population15 = 28
                 });
 
            context.SaveChanges();
 
                base.Seed(context);
 
        }
    }
}
 
Here we have created the DataContext and DatabaseInitalize class. We will use DataContext class in the repository class. The CityRepository class will implement the ICityRepository interface from the core project and perform the CRUD operations using the DataContext class. CityRepository class can be implemented as shown in the listing below:
 
using System.Collections.Generic;
using System.Linq;
using WebApiRepositoryPatternDemo.Core.Entities;
using WebApiRepositoryPatternDemo.Core.Interfaces;
 
namespace WebApiRepositoryPatternDemo.Infrastructure.Repository
{
    public class CityRepository : ICityRepository
    {
        CityDataContext context = new CityDataContext();
        public void Add(Core.Entities.City b)
        {
            context.Cities.Add(b);
            context.SaveChanges();
          
        }
 
        public void Edit(Core.Entities.City b)
        {
            context.Entry(b).State = System.Data.Entity.EntityState.Modified;
        }
 
        public void Remove(string Id)
        {
            City b = context.Cities.Find(Id);
            context.Cities.Remove(b);
            context.SaveChanges();
        }
 
        public IEnumerable<Core.Entities.City> GetCity()
        {
            return context.Cities;
        }
 
        public Core.Entities.City FindById(int Id)
        {
            var c = (from r in context.Cities where r.Id == Id select r).FirstOrDefault();
            return c;
        }
    }
}
 
Implementation of the CityRepository class is very simple. We are using the usual LINQ to Entity code to perform the CRUD operations, and after implementing all the classes, the infrastructure project should look as shown in the image below:
 
 
Exposing CRUD operations as ASP.NET Web API
To expose CRUD operations as Web API, let us go ahead and create the Web API project. In the Web API project we need to add following references:

1.       Reference of the core project

2.       Reference of the infrastructure project

3.       Reference of the Entity framework

After adding all the references in the Web API project, copy the connection string (added in the previous step cityconnectionstring) from the APP.Config of the infrastructure project to the web.config of the Web API project.  Next, open the Global.asax file and in the Application_Start() method add below lines of code. These lines of code will make sure that seed data has been inserted to the database.
 
            CityDbInitalize db = new CityDbInitalize();
            System.Data.Entity.Database.SetInitializer(db);
 
At this point, build the Web API project then right click on the Controllers folder and a new controller. Create a new controller with the scaffolding choosing Web API 2 Controller with actions, using the Entity Framework option as shown in the image below:
 
Next to add the Controller, select the City class as the Model class and the CityDataContext class as the Data context class.
 
 
Once you click on Add, you will find a Web API controller has been created with the name CitiesController in the Controllers folder. At this point when you go ahead and run the Web API, you should able to GET the Cities in the browser as shown in the image below:
 
Here we have created the Web API using the Entity Framework Code First approach and the Repository pattern. Now we’ll perform the HTTP GET operation on the Web API created here in section 2 of this article to create the Ignite UI chart in your AngularJS application.
 
Section: 2: Using Ignite UI in AngularJS application
In this section we’ll learn how to create two charts, one using data from the Web API and another using the static array. Our final output will look more or less like the following image:
 
To start, let’s add the following files in the AngularJS application project:

1.       IgniteUI-Angular: you can find IgniteUI-Angular project on GutHub here . To be specific, from the IgniteUI-Angular project you only need igniteui-angular.js file.

2.       IgniteUI: You can find free trial download of Ignite UI here. In Visual Studio, Ignite UI package can be added using the NuGet package manager.

 
Adding References
After adding the required file in the project, add required references on the HTML as shown in the listing below:
    <link href="Content/Infragistics/css/structure/infragistics.css" rel="stylesheet" />
    <script src="Scripts/modernizr-2.7.2.js"></script>
    <script src="Scripts/jquery-2.1.3.js"></script>
    <script src="Scripts/jquery-ui-1.10.3.js"></script>
    <script src="Scripts/Infragistics/js/infragistics.core.js"></script>
    <script src="Scripts/Infragistics/js/infragistics.dv.js"></script>
    <script src="Scripts/Infragistics/js/infragistics.lob.js"></script>  
    <script src="Scripts/angular.js"></script>
    <script src="igniteui-angular.js"></script>
    <script src="Service.js"></script>
    <script src="default.js"></script>
 
We are adding references of:

·         jQuery and jQuery UI

·         Ignite UI Core, dv and lob files

·         Igniteui-angular file

·         AngularJS

·         Service.js and default.js are the files we are going to create later.

 
AngularJS Service
After adding all the references, let us create an AngularJS service to perform HTTP GET operation and fetch data from the Web API (later in this article, you can find how to create ASP.NET Web API). AngularJS service can be created as shown in the listing below:

Service.js
var app = angular.module('dataservice', []);
 
app.factory('populationData', ['$http', function ($http) {

    var populationData = {};

 

    populationData.data = function () {

        alert("hi");

        return $http.get('http://localhost:56649/API/CITIES');

    };

 

    return populationData;

 

}]);

 
Here we are using the AngularJS inbuilt service $http to perform the HTTP get operations. We are passing the Web API GET operation URL (created in section 1) in the $http.get function. Do not forget to replace the URL with your Web API URL!
 
AngularJS Controller
To use the service created above and the Ignite UI chart in application, we need to add the IgniteUI-Angular module and the service module in the main module of the app. We are adding a dependency of the modules listed below:

1.       Igniteui-directives module : to work with the charts

2.       Dataservice module: we created this module to fetch data from the Web API. (Refer the AngularJS service section)

We can create the controller as shown in the listing below:
 
Default.js
var myapp = angular.module('myapp', ['igniteui-directives', 'dataservice']);
 
myapp.controller('dataChartController', ['$scope', 'populationData', function ($scope, populationData) {
 
    $scope.a = [];    
    getData();
    function getData() {
        populationData.data()
            .success(function (cities) {
                $scope.a = cities;
            })
            .error(function (error) {
                $scope.status = 'Unable to load population data: ' + error.message;
                console.log('error');
            });
    }
 
    $scope.data = [

          { "Subject": "Physics", "July": 100 },

          { "Subject": "Maths", "July": 88 },

          { "Subject": "English", "July": 96 },

          { "Subject": "History", "July": 110 },

          { "Subject": "Geography", "July": 92 }

    ];

    $scope.dataChart = $scope.data;
}]);
 
 
In the above controller, we are creating two variables which will set as datasource of the charts.

1.       $scope.a: Value of this variable would be set to the returned data from the Web API. Initially we are setting value of $scope.a to empty array and then calling populationData.data() function from the service to set its value.

2.       $scope.data: This value is set to static array.

 
AngularJS View
On the view, we are going to create two Ignite UI charts.

1.       First chart is displaying data from the Web API, hence its data source is set to $scope.a

2.       Second chart is displaying data from the static array, hence its data source is set to $scope.data

 
  <h1>Ignite UI + AngularJS</h1>
    <div class="row" ng-controller="dataChartController">
        <div class="col-md-6">
           
            <h2>Countries Population[Web API]</h2> <br/>
           
                <ig-data-chart id="datachart1" data-source="a">
                    <axes>
                        <axis name="NameAxis"
                              type="categoryX"
                              title="Name"
                              label="Name"></axis>
 
                        <axis name="PopulationAxis"
                              type="numericY"
                              minimumvalue="0"
                              title="Milions of People"></axis>
                    </axes>
                    <series>
                        <series name="2001Population"
                                type="column"
                                is-highlighting-enabled="true"
                                is-transition-in-enabled="true"
                                x-axis="NameAxis"
                                y-axis="PopulationAxis"
                                value-member-path="Population01">
                        </series>
                        <series name="2015Population"
                                type="column"
                                is-highlighting-enabled="true"
                                is-transition-in-enabled="true"
                                x-axis="NameAxis"
                                y-axis="PopulationAxis"
                                value-member-path="Population15">
                        </series>
                    </series>
                </ig-data-chart>
         
 
       </div>
        <div class="col-md-6">
                <h2>Subjects Data [Static Array]</h2> <br />
                <ig-data-chart id="datachart1" data-source="dataChart">
                    <axes>
                        <axis name="NameAxis"
                              type="categoryX"
                              title="Subjects"
                              label="Subject"></axis>
 
                        <axis name="NumberOfQuestionAxis"
                              type="numericY"
                              minimumvalue="0"
                              title="Number of Questions"></axis>
                    </axes>
                    <series>
                        <series name="July"
                                type="column"
                                is-highlighting-enabled="true"
                                is-transition-in-enabled="true"
                                x-axis="NameAxis"
                                y-axis="NumberOfQuestionAxis"
                                value-member-path="July">
                        </series>
                    </series>
                </ig-data-chart>
            </div>
        </div>
 
For the first chart, let’s bind to data from the Web API:

1.       Data-source is set to $scope.a

2.       X Axis to set to Name. You need to make sure that the Name property exists in the returned JSON from the Web API

3.       Y Axis is set to numeric value.

4.       There are two series. The value-member-path of the first series  is set to Population01 column and value-member-path of the second series is set to Population15 column.

 
For the second chart, bind to static array:

1.       Data-source is set to $scope.dataChart

2.       X Axis to set to Subjects. You need to make sure that the Subjects property exists in the array.

3.       Y Axis is set to numeric value.

4.       There is only one series and value-member-path is set to July column.

When we run the application, the Ignite UI chart will be rendered in our AngularJS application as shown in the image below:
 
And there you go! By following these simple steps, you can use Ignite UI data charts in an AngularJS application. I hope you find this article useful. Have something to add? Leave a comment. Thanks for reading!