December 7, 2019

Part 3 – Angular 8 CRUD: Using ChartJs To Represent Data

Pie Chart Tab

Welcome everyone to Part 3 of our Angular 8 CRUD series. In this part we are going to integrate ChartJs library with our application to show some graphs related to our expenses.

In Part 1 and 2 we have implemented the CRUD app for basic expense manager using Asp.Net Web API and Angular 8.

Update Back-end API

We will implement bar chart and pie chart to showcase expenses by month and by category in our app. Let us first update our API to send the required data set.

Adding BarChartModel and PieChartModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AngularJwt_Api.Models
{
    public class BarChartModel
    {
        public string Month { get; set; }
        public decimal? Amount { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AngularJwt_Api.Models
{
    public class PieChartModel
    {
        public string Category { get; set; }
        public decimal? Amount { get; set; }
    }
}

Add Reports Controller

Create a new controller named ReportController which we will use to get the data for our charts. We will have two HttpGet methods, one each for getting Expenses Per Category and Expenses Per Month. Use the below code to implement it.

using AngularJwt_Api.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Cors;

namespace AngularJwt_Api.Controllers
{
    [Route("reports")]
    [EnableCors("*", "*", "*")]
    public class ReportController : ApiController
    {
        AngularCrudDb dbContent = new AngularCrudDb();

        [HttpGet]
        [Route("getExpPerCat")]
        public List<PieChartModel> GetExpensesPerCategory()
        {
            var expenses = (from exp in dbContent.Expenses
                            join cat in dbContent.Categories
                            on exp.ExpenseCategory equals cat.Id
                            group exp by cat.ExpenseCategory into groupData
                            select new PieChartModel
                            {
                                Category = groupData.Key,
                                Amount = groupData.Sum(x => x.ExpenseAmount)
                            }
                            ).ToList();

            return expenses;
        }

        [HttpGet]
        [Route("getExpPerMonth")]
        public List<BarChartModel> GetExpensesPerMonth()
        {
            var expenses = (from exp in dbContent.Expenses
                            group exp by new { month = exp.Date.Value.Month } into groupData
                            select new BarChartModel
                            {
                                Month = groupData.Key.month.ToString(),
                                Amount = groupData.Sum(x => x.ExpenseAmount)
                            }
                            ).ToList();

            return expenses;
        }
       
    }
}

So our two new endpoints are ready. Let us get back to our Angular 8 app now.

Update Angular 8 App

Install Chart.Js

Use command “npm install chart.js –save” to install Chart Js liberary in our project.

Angular Components and Model

Now, create 2 new components BarChart, PieChart and models BarChartData, PieChartData using Angular CLI. Both the models will have similar fields as in their counterpart API models.

barchart.component.html

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import {Chart} from 'chart.js';
import { BarChartData } from './../../shared/BarChartData';



@Component({
  selector: 'app-barchart',
  templateUrl: './barchart.component.html',
  styleUrls: ['./barchart.component.css']
})
export class BarchartComponent implements OnInit {

  data: BarChartData[];  
  url = 'http://localhost:51888/getExpPerMonth';  
  Months = [];  
  Amount = [];  
  barchart = [];  
  constructor(private http: HttpClient) { }  
  
  ngOnInit() {  
    this.http.get(this.url).subscribe((result: BarChartData[]) => {  
      result.forEach(x => {  
        this.Months.push(x.Month);  
        this.Amount.push(x.Amount);  
      });  
      this  
      this.barchart = new Chart('canvas1', {  
        type: 'bar',  
        data: {  
          labels: this.Months,  
          datasets: [  
            {  
              data: this.Amount,  
              borderColor: '#3cba9f',  
              backgroundColor: [  
                "#3cb371",  
                "#0000FF",  
                "#9966FF",  
                "#4C4CFF",  
                "#00FFFF",  
                "#f990a7",  
                "#aad2ed",  
                "#FF00FF",  
                "Blue",  
                "Red",  
                "Blue"  
              ],  
              fill: true  
            }  
          ]  
        },  
        options: {  
          legend: {  
            display: false  
          },  
          scales: {  
            xAxes: [{  
              display: true  
            }],  
            yAxes: [{  
              display: true  
            }],  
          }  
        }  
      });  
    });  
  }
}
  • Import Chart from chart.js which we installed earlier
  • Use the HttpGet method to get the data from endpoint and map it to the local arrays Months and Amount
  • Labels will have the data for Y axis hence the months here
  • Data will be mapped to the amount which will be shown on the X axis.
  • “canvas1” is the ID of canvas html element where this data will be shown

You can read more about Chart.js customization in their official documentation.

barchart.component.html

<div class="container">
    <div class="row">
        <div class="col-md-8 mx-auto p-5 m-3">
            <canvas id="canvas1"></canvas>
        </div>
    </div>
</div>

piechart.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { PieChartData } from './../../shared/PieChartData';
import {Chart } from 'chart.js';

@Component({
  selector: 'app-piechart',
  templateUrl: './piechart.component.html',
  styleUrls: ['./piechart.component.css']
})
export class PiechartComponent implements OnInit {

  data: PieChartData[];  
  url = 'http://localhost:51888/getExpPerCat';  
  Category = [];  
  Amount = [];  
  chart = [];  
  constructor(private httpClient: HttpClient) { }  
  
   ngOnInit() {  
    this.httpClient.get(this.url).subscribe((result: PieChartData[]) => {  
      result.forEach(x => {  
        this.Category.push(x.Category);  
        this.Amount.push(x.Amount);  
      });  
     this  
      this.chart = new Chart('canvas', {  
        type: 'pie',  
        data: {  
          labels: this.Category,  
          datasets: [  
            {  
              data: this.Amount,  
              borderColor: '#3cba9f',  
              backgroundColor: [  
                "#3cb371",  
                "#0000FF",  
                "#9966FF",  
                "#4C4CFF",  
                "#00FFFF",  
                "#f990a7",  
                "#aad2ed",  
                "#FF00FF",  
                "Blue",  
                "Red",  
                "Blue"  
              ],  
              fill: true  
            }  
          ]  
        },  
        options: {  
          legend: {  
            display: true  
          },  
          scales: {  
            xAxes: [{  
              display: false  
            }],  
            yAxes: [{  
              display: false  
            }],  
          }  
        }  
      });  
    });  
  }
}

piechart.component.html

<div class="container">
    <div class="row">
        <div class="col-md-8 mx-auto p-5 m-3">
            <canvas id="canvas"></canvas>
        </div>
    </div>
</div>

Let us now implement some Routing to show are charts in a tabular structure

Implement Routing

Create Routes in app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ExpensesComponent } from './custom-components/expenses/expenses.component';
import { ExpenseItemComponent } from './custom-components/expense-item/expense-item.component';
import { PiechartComponent } from './custom-components/piechart/piechart.component';
import { BarchartComponent } from './custom-components/barchart/barchart.component';



const routes: Routes = [
  {path:"barChart", component:BarchartComponent},
  {path:"pieChart", component:PiechartComponent},
  {path:"home",component:ExpensesComponent}
  
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Add Links for Route in app.component.html

  • Here we will add a simple bootstrap navigation to create three tabs one each for Expense, Bar Chart and Pie Chart
  • To each tab we will assign the routes we have just created
  • We will finally define a <router-outlet> to show the actual component based on route selected through the tabs.
<div class="container">
    <div class="row">
        <div class="col-md-6 my-3">
            <ul class="nav nav-tabs">
                <li class="active nav-item">
                    <a class="nav-link  text-dark" routerLink="/home" routerLinkActive="bg-success" href="#">Expenses</a></li>
                <li class="active nav-item">
                    <a class="nav-link  text-dark" routerLink="/barChart" routerLinkActive="bg-success" href="#">Bar Chart</a></li>
                <li class="nav-item">
                    <a href="#" routerLink="/pieChart" routerLinkActive="bg-success" class="nav-link  text-dark">Pie Chart</a></li>
            </ul>
        </div>
    </div>
    <div class="container">
        <router-outlet></router-outlet>
    </div>
</div>

That is it! We have integrated Chart.Js with our Angular 8 app. Below are the screenshot for the final application.

Thanks for following this three part series. If you found it useful I would be great full if you can share the content and follow us on our social media profiles.

Happy Coding!!!

Leave a Reply

Your email address will not be published. Required fields are marked *