Click here to Skip to main content
15,867,918 members
Articles / Web Development / ASP.NET / ASP.NET Core

Dynamic Highcharts – ASP.NET Core, Angular6

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
14 Aug 2018CPOL3 min read 17.2K   169   17   2
In this post, we are going to implement dynamic highchart with Angular6 and ASP.NET Core.

Introduction

In the previous article, we explored how a Single Page Application (SPA) sample can be put together using ASP.NET Core & Angular from scratch.

Based on the previous post, this article is extended to implement charting. We are going to modify/extend the existing sample application by downloading the full source code from github.

Let’s get started by opening the existing application, first of all, we are going to add packages to our application.

Install Node Packages

Let’s add frontend packages to our application. We need to modify package.json file. Open package.json file, then add listed dependencies from below.

Dependencies:

JavaScript
"angular-highcharts": "^6.2.6",
"highcharts": "^6.1.1"

Dev Dependencies:

JavaScript
"@types/highcharts": "^5.0.22",

Here’s our list of frontend package dependencies.

JavaScript
{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "dependencies": {
    "@angular/common": "^6.0.2",
    "@angular/compiler": "^6.0.2",
    "@angular/core": "^6.0.2",
    "@angular/forms": "^6.0.2",
    "@angular/http": "^6.0.2",
    "@angular/platform-browser": "^6.0.2",
    "@angular/platform-browser-dynamic": "^6.0.2",
    "@angular/router": "^6.0.2",
    "@angular/upgrade": "^6.0.2",
    "bootstrap": "^4.1.1",
    "core-js": "^2.5.6",
    "reflect-metadata": "^0.1.12",
    "rxjs": "^6.1.0",
    "systemjs": "^0.21.3",
    "zone.js": "^0.8.26",
    "angular-highcharts": "^6.2.6",
    "highcharts": "^6.1.1"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.46",
    "typescript": "^2.8.3",
    "typings": "^2.1.1",
    "@types/node": "^10.0.4",
    "@types/highcharts": "^5.0.22",
    "concurrently": "^3.5.1",
    "json-server": "^0.12.2",
    "gulp": "^3.9.1",
    "gulp-concat": "^2.6.1",
    "gulp-rename": "^1.2.2",
    "gulp-cssmin": "^0.2.0",
    "gulp-uglify": "^3.0.0",
    "gulp-htmlclean": "^2.7.20",
    "rimraf": "^2.6.2"
  }
}

After installation of all packages, let’s transfer the required libraries from node_modules folder to “wwwroot/lib”.

Manage Installed Packages

We need to add the below listed task to gulp file, which will transfer the newly added package libraries to “wwwroot/lib” folder.

JavaScript
gulp.src('./node_modules/angular-highcharts/**/*.js')
    .pipe(gulp.dest(root_path.package_lib + 'angular-highcharts'));

gulp.src('./node_modules/highcharts/**.js')
    .pipe(gulp.dest(root_path.package_lib + 'highcharts'));

Here’s the modified gulp file:

JavaScript
/// <binding AfterBuild='build-all' />

var gulp = require("gulp"),
    rimraf = require("rimraf"),
    concat = require("gulp-concat"),
    cssmin = require("gulp-cssmin"),
    uglify = require("gulp-uglify"),
    rename = require("gulp-rename");

var root_path = {
    webroot: "./wwwroot/"
};

//library source
root_path.nmSrc = "./node_modules/";

//library destination
root_path.package_lib = root_path.webroot + "lib/";

gulp.task('copy-lib-js', function () {

    gulp.src('./node_modules/core-js/**/*.js')
        .pipe(gulp.dest(root_path.package_lib + 'core-js'));

    gulp.src('./node_modules/@angular/**/*.js')
        .pipe(gulp.dest(root_path.package_lib + '@angular'));

    gulp.src('./node_modules/zone.js/**/*.js')
        .pipe(gulp.dest(root_path.package_lib + 'zone.js'));

    gulp.src('./node_modules/systemjs/**/*.js')
        .pipe(gulp.dest(root_path.package_lib + 'systemjs'));

    gulp.src('./node_modules/reflect-metadata/**/*.js')
        .pipe(gulp.dest(root_path.package_lib + 'reflect-metadata'));

    gulp.src('./node_modules/rxjs/**.js')
        .pipe(gulp.dest(root_path.package_lib + 'rxjs'));

    gulp.src('./node_modules/angular-highcharts/**/*.js')
        .pipe(gulp.dest(root_path.package_lib + 'angular-highcharts'));

    gulp.src('./node_modules/highcharts/**.js')
        .pipe(gulp.dest(root_path.package_lib + 'highcharts'));
});

gulp.task("copy-all", ["copy-lib-js"]);
//Copy End

gulp.task('min-js', function () {
    gulp.src(['./clientapp/**/*.js'])
        .pipe(uglify())
        .pipe(gulp.dest(root_path.webroot + 'app'))
});

gulp.task('copy-html', function () {
    gulp.src('clientapp/**/*.html')
        .pipe(gulp.dest(root_path.webroot + 'app'));
});

gulp.task("build-all", ["min-js", "copy-html"]);
//Build End

Right click on gulpfile.js, then go to “Task Runner Explorer”.

Image 1

From the new window, refresh the task, then right click on task to run it like the below screen.

Image 2

As we can see, our required libraries are loaded in “wwwroot/lib” folder.

Image 3

Before importing module, we need to modify SystemJS by adding the below listed bundle to System.config() function.

JavaScript
'angular-highcharts': 'npm:angular-highcharts/angular-highcharts.umd.js',
'highcharts': 'npm:highcharts/highcharts.src.js'

SystemJS Config: systemjs.config.js

JavaScript
/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
    System.config({
        paths: {
            // paths serve as alias
            'npm:': '/lib/'
        },
        // map tells the System loader where to look for things
        map: {
            // our app is within the app folder
            'app': 'app',

            // angular bundles
            '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
            '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
            '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
            '@angular/platform-browser': 
                'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
            '@angular/platform-browser-dynamic': 
                'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
            '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
            '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
            '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',

            // highchart bundles
            'angular-highcharts': 'npm:angular-highcharts/angular-highcharts.umd.js',
            'highcharts': 'npm:highcharts/highcharts.src.js',

            // other libraries
            'rxjs': 'npm:rxjs',
            'rxjs-compat': 'npm:rxjs-compat',
            'rxjs/operators': 'npm:rxjs/operators'
        },
        // packages tells the System loader how to load when no filename and/or no extension
        packages: {
            'app': {
                main: 'main.js',
                defaultExtension: 'js',
                meta: {
                    '': {
                        format: 'cjs'
                    }
                }
            },
            'rxjs': {
                main: 'index.js',
                defaultExtension: 'js'
            },
            'rxjs/operators': {
                main: 'index.js',
                defaultExtension: 'js'
            }
        }
    });
})(this);

TypeScript Configuration

We need to add new types "highcharts" in compiler options, the below code snippet is for tsconfig.json file.

Configure Typescript: tsconfig.json

JavaScript
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ],
    "types": [
      "core-js",
      "highcharts"
    ]
  },
  "includes": [
    "/**/*.ts"
  ]
}

Root Module: Now let’s import newly added chart module, component in module.ts.

JavaScript
import { ChartModule } from 'angular-highcharts';

Below is the updated code snippet in module.ts.

JavaScript
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Routes, RouterModule } from '@angular/router';
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { ChartModule } from 'angular-highcharts';

//Components
import { AppComponent } from './component/app/component';
import { HomeComponent } from './component/home/component';
import { AboutComponent } from './component/about/component';
import { UserComponent } from './component/user/component';
import { ChartComponent } from './component/chart/component';

//Routes
const routes: Routes = [
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'home', component: HomeComponent },
    { path: 'about', component: AboutComponent },
    { path: 'user', component: UserComponent },
    { path: 'chart', component: ChartComponent }
];

@NgModule({
    imports: [BrowserModule, HttpModule, FormsModule, 
              ReactiveFormsModule, RouterModule.forRoot(routes), ChartModule],
    declarations: [AppComponent, HomeComponent, AboutComponent, UserComponent, ChartComponent],
    bootstrap: [AppComponent]
})

export class AppModule { }

Next, we will create SQL Database tables.

Creating Database

Let’s create a database in MSSQL Server. Here is the table where we are storing data. Run the below script in query window to create a new database.

SQL
CREATE DATABASE [dbCore]

Creating Table

SQL
USE [dbCore]
GO

/****** Object:  Table [dbo].[User]    Script Date: 8/15/2018 9:22:00 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[User](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[FirstName] [nvarchar](250) NULL,
	[LastName] [nvarchar](250) NULL,
	[Email] [nvarchar](250) NULL,
	[Phone] [nvarchar](50) NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, _
       ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

/****** Object:  Table [dbo].[UserMarks]    Script Date: 8/15/2018 9:22:00 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[UserMarks](
	[id] [int] NOT NULL,
	[userId] [int] NULL,
	[mark] [decimal](18, 2) NULL,
 CONSTRAINT [PK_UserMarks] PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, _
       ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Scaffolding MSSQL Database

We are going to re-generate EF models from the existing database using reverse engineering using command in Package Manager Console. Image 4

Command

JavaScript
Scaffold-DbContext "Server=DESKTOP-7OJNKVF;Database=dbCore;Trusted_Connection=True;" 
Microsoft.EntityFrameworkCore.SqlServer -Output serverapp/models -Force

As we can see from solution explorer, models folder is created with Context & Entities.

Image 5

Now open the DbContext file, then add a constructor to pass configuration like connectionstring into the DbContext.

C#
public dbCoreContext(DbContextOptions<dbCoreContext> options) : base(options)
{
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    //if (!optionsBuilder.IsConfigured)
    //{
    //    #warning To protect potentially sensitive information in your connection string, 
    //    you should move it out of source code. 
    //    See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
    //    optionsBuilder.UseSqlServer
    //    (@"Server=DESKTOP-7OJNKVF;Database=dbCore;Trusted_Connection=True;");
    //}
}

Modify WebAPI

Add the below result function to existing web-api to retrieve result data from database.

C#
// GET: api/Values/GetResult
[HttpGet, Route("GetResult")]
public async Task<List<vmMarks>> GetResult()
{
    List<vmMarks> query = null;

    try
    {
        using (_ctx)
        {
            query = await (from um in _ctx.UserMarks
                            join m in _ctx.User on um.UserId equals m.Id
                            select new vmMarks
                            {
                                mid = (int)m.Id,
                                mName = m.FirstName + " " + m.LastName,
                                mMark = (decimal)um.Mark
                            }).OrderByDescending(x => x.mMark).ToListAsync();
        }
    }
    catch (Exception ex)
    {
        ex.ToString();
    }

    return query;
} 

All right, our WebAPI is modified and ready to retrieve data. Our next step is to prepare client model, component and services to interact with WebAPIs. Let’s create a typescript model class, then use it in another component by importing like:

JavaScript
//Model
import { ResultModel } from './model';

Typescript Model: ResultModel

JavaScript
export class ResultModel {
    mid: number;
    mName: string;
    mMark: any;
} 

Component: ChartComponent

JavaScript
import { Component } from '@angular/core';
import { ResultModel } from './model';
import { ResultService } from './service';
import { Chart } from 'angular-highcharts';

@Component({
    selector: 'chart',
    templateUrl: './app/component/chart/chart.html',
    providers: [ResultService]
})

export class ChartComponent {
    public marks: ResultModel[];
    public chart: Chart;

    title: string;
    constructor(private resService: ResultService) {
        this.title = ''
    }

    ngOnInit() {
        this.getChart();
    }

    //Get All 
    getChart() {

        //debugger
        this.resService.getall().subscribe(
            response => {
                this.marks = response;
                let chartData = [];
                for (var i = 0; i < this.marks.length; i++) {
                    chartData.push({
                        "name": this.marks[i].mName,
                        "y": this.marks[i].mMark,
                        sliced: true,
                        selected: true
                    })
                }

                this.chart = new Chart({
                    chart: {
                        plotBackgroundColor: null,
                        plotBorderWidth: null,
                        plotShadow: false,
                        type: 'pie',
                        backgroundColor: null,
                        options3d: {
                            enabled: true,
                            alpha: 45,
                            beta: 0
                        }
                    },
                    title: {
                        text: 'Angular-6 + Highcharts-6',
                    },
                    subtitle: {
                        text: 'Result Pie-Chart!'
                    },
                    tooltip: {
                        pointFormat: '{series.name}: <b>{point.y}</b>'
                    },
                    plotOptions: {
                        pie: {
                            allowPointSelect: true,
                            cursor: 'pointer',
                            depth: 35,
                            dataLabels: {
                                enabled: true,
                                format: '<b>{point.name}</b>: {point.percentage:.1f} %'
                            }
                        }
                    },
                    series: [{
                        name: 'Total Mark',
                        data: chartData
                    }]
                });

            }, error => {
                console.log(error);
            }
        );
    }
}

Http Client Services: ResultService

JavaScript
import { Injectable, Component } from '@angular/core';
import { HttpModule, Http, Request, RequestMethod, Response, RequestOptions, Headers } 
         from '@angular/http';
import { Observable, Subject, ReplaySubject } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

//Model
import { ResultModel } from './model';

@Component({
    providers: [Http]
})

@Injectable()

export class ResultService {
    public headers: Headers;
    public _getUrl: string = '/api/Values/GetResult';

    constructor(private _http: Http) { }

    //Get
    getall(): Observable<ResultModel[]> {
        return this._http.get(this._getUrl)
            .pipe(map(res => <ResultModel[]>res.json()))
            .pipe(catchError(this.handleError));
    }


    private handleError(error: Response) {
        return Observable.throw(error.json().error || 'Opps!! Server error');
    }
}

Http View: chart.html

HTML
<div class="container-fluid">
    <div class="row">
        <h2>{{title}}</h2>
        <div [chart]="chart"></div>
    </div>
</div>

Test in Browser

Now it’s time to build & run the application, go to chart menu, as we can see from the below screenshot, pie chart is generated dynamically.

Image 6 Summary

In this sample, we have combined ASP.NET Core & Angular to create the sample SPA app without any CLI, learn how to start with an empty ASP.NET Core application to serve static HTML page.

We also have deep dived into the latest frontend technology like Angular6 from scratch to build a single page application, have a short overview of Angular6 dependencies & also have ideas of module, components. Then we have performed some database operation using our sample application. Finally, we have implemented Dynamic Highchart. Hope this will help.

License

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


Written By
Software Developer (Senior) s3 Innovate Pte Ltd
Bangladesh Bangladesh
Hi, I am Shashangka Shekhar,

Working with Microsoft Technologies. Since March 2011, it was my first step to working with Microsoft Technologies, achieved bachelor’s degree on Computer Science from State University of Bangladesh(Dhaka). Have 12+ years of professional experience, currently working as Technical Lead at Surbana Jurong Private Limited.

I believe in desire of learning & also love to be a part of .Net Community by sharing knowledge’s.

Comments and Discussions

 
QuestionLazy loading Pin
Member 1394346027-Aug-18 22:32
Member 1394346027-Aug-18 22:32 
QuestionD3 - ASP.NET Core, Angular6 Pin
Aurobinda Rana27-Aug-18 22:26
professionalAurobinda Rana27-Aug-18 22:26 

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

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