65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 AngularJS、Web API 和 Json 的 Flot 图表

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2015 年 6 月 26 日

CPOL

3分钟阅读

viewsIcon

22242

使用 Web API 和 Json 绘制 Flot 图表

引言

我当时正在评估用于我项目的 JavaScript 图表框架。我发现了 jQuery Flot 库,它支持各种图表。在本文中,我尝试使用 jQuery Flot 库绘制一个多时间轴图表。它使用 ASP.NET Web API 从数据库获取数据。我遇到的问题是获取数据,数据的格式必须能够绑定到 Flot 图表。我不得不对 Json 数据进行大量尝试,最终才使其与 Flot 一起工作。

使用代码

让我解释一下这个场景。需求是显示票务数据 - 一个月内收到的总票数、当月解决的总票数、当月未决的总票数。这些数据需要在单个具有多个轴的图表上绘制。代码分为三个部分

1. 数据库

2. WebAPI

3. 用于显示图表的 Angular JS 客户端应用程序

Web API 和 Angular JS 客户端应用程序是独立的 Visual Studio 解决方案。我这样做是为了了解如何启用 CORS。

首先,我们将了解数据库对象。数据存储在一个表中,并在其顶部创建一个视图以获取数据。

表脚本

CREATE TABLE [dbo].[Tickets1](
[TicketId] [int] NOT NULL, 
[CreationDate] [datetime] NOT NULL,
[TicketStatus] [smallint] NOT NULL,
[ResolvedDate] [datetime] NULL,
CONSTRAINT [PK_Tickets1] PRIMARY KEY CLUSTERED
( [TicketId] 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

视图脚本

CREATE VIEW [dbo].[MonthWiseTickets]
AS
SELECT        newid() AS Id, MonthYear, 
[1] AS ResolvedTickets, [0] AS OpenTickets, [1] + [0] AS TotalTickets
FROM         (SELECT     CAST(YEAR(creationdate) AS VARCHAR(4)) + '-' + CONVERT(varchar(2), 
creationdate, 101) + '-'+
'01'  AS MonthYear, creationdate, TicketStatus
FROM            Tickets1) up PIVOT (Count(CreationDate) FOR TicketStatus IN ([1], [0])) AS pvt

上述视图以以下格式给出输出

我们的数据库现在已设置好,接下来我们创建一个 Web API 从数据库获取数据。因此,我们直接使用 Visual Studio 创建一个 Web API 项目。

Web API

该项目的基本结构如下。首先,我们将创建模型类,然后启用 CORS,然后创建控制器以从数据库获取数据。

 

我们在 Models 文件夹内创建一个 Model Tickets.cs,它将表示 SQL 视图的字段。

public class Ticket

{

public string Id { get; set; }

public string MonthYear { get; set; }

public int ResolvedTickets { get; set; }

public int OpenTickets { get; set; }

public int TotalTickets { get; set; }

}

然后我们需要启用 CORS,以便客户端应用程序可以调用 Web API。为此,我们需要从 NuGet 安装 CORS 包。完成后,打开 WebApiConfig.cs 并添加以下代码行。

// Web API configuration and services


config.EnableCors();

现在我们需要创建一个控制器来调用数据库中的视图。我们添加一个新的控制器文件 FlotChartController。以下是控制器的代码,注意第一行,我们在其中为客户端应用程序启用 CORS。

然后我们使用 ADO.NET 使用命令对象调用 SQL 视图。

[EnableCors(origins: "https://:52306", headers: "*", methods: "*")]

public class FlotChartController : ApiController

{

public dynamic Get()

{

List<Ticket> Tickets = new List<Ticket>();

ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["charts"];

using (SqlConnection con =

new SqlConnection(settings.ConnectionString.ToString()))

{

SqlCommand cmd = con.CreateCommand();

cmd.CommandText = "Select * From MonthWiseTickets order by CONVERT(datetime,monthyear)";

cmd.CommandTimeout = 120;

cmd.CommandType = CommandType.Text;

con.Open();

SqlDataReader reader = cmd.ExecuteReader();

while (reader.Read())

{

Ticket ticket = new Ticket();

ticket.Id = reader.GetGuid(0).ToString();

ticket.MonthYear = reader.GetString(1);

ticket.ResolvedTickets = reader.GetInt32(2);

ticket.OpenTickets = reader.GetInt32(3);

ticket.TotalTickets = reader.GetInt32(4);

Tickets.Add(ticket);

}

}

var ret = new[] {

new { label="Open Tickets", data = Tickets.Select(x=>new string[]{ x.MonthYear, x.OpenTickets.ToString() })},

new { label="Resolved Tickets", data = Tickets.Select(x=>new string[]{ x.MonthYear, x.ResolvedTickets.ToString() })},

new { label="Total Tickets", data = Tickets.Select(x=>new string[]{ x.MonthYear, x.TotalTickets.ToString() })},

};

return ret;

}

}

现在我们的服务器组件已准备就绪,我们现在需要创建客户端应用程序来使用 Web API。在下一节中,我们将看到如何设置 AngularJS 客户端应用程序。

AngularJS

以下是设置客户端应用程序所需库的步骤

1. 在 Visual Studio 中创建一个空的 ASP.NET 项目

2. 添加 jQuery、AngularJS 和 Flot 的 Nuget 包

3. 添加 Angular Flot 的模块

这是添加这些库后您的解决方案的样子。

现在在项目中添加一个名为 App 的文件夹,并添加两个子文件夹 Controllers 和 Services。

 

现在让我们开始添加一些代码,创建一个 app.js 文件并添加以下代码。当 index 页面加载时,这将实例化我们的应用程序。

var app = angular.module('MorrisApp', ['ngRoute', 'angular-flot']);

var serviceBase = 'https://:51419/';

app.constant('ngAuthSettings', {

apiServiceBaseUri: serviceBase,

});

在 services 文件夹下添加 flotService.js 文件,这将调用我们之前创建的 Web API。

'use strict';

app.factory('flotService', ['$http', 'ngAuthSettings', function ($http, ngAuthSettings) {

var serviceBase = ngAuthSettings.apiServiceBaseUri;

var flotServiceFactory = {};

var _getMonthlyTicketsSummary = function () {

return $http.get(serviceBase + 'api/FlotChart').then(function (results) {

return results;

});

};

flotServiceFactory.getMonthlyTicketsSummary = _getMonthlyTicketsSummary;

return flotServiceFactory;

}]);

 

现在是编写控制器以调用服务并绘制图表的主要部分。

app.controller('FlotCtrlJson', ['$scope', 'flotService', function ($scope, flotService) {

//declare an array for month names to be dispaled on the x axis

var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

// generate the tool tip

function getTooltip(label, x, y) {

var date = new Date(x)

return label + " for " + monthNames[date.getMonth()] + " " + date.getFullYear() + " are " + y;

}

// set options for the flot graph

$scope.options = {

legend: {

container: "#legendjson",

show: true,

noColumns: 3,


},

axisLabels: {

show: true

},

xaxis: {

mode: "time", minTickSize: [1, "month"], timeformat: " %b %y",

axisLabel: "Month",

monthNames: monthNames,

//ticks: [[1,"Jan"],[2,"Feb"]]

},

yaxes: [{

position: "left",

axisLabel: "Total Tickets",

axisLabelUseCanvas: true,

axisLabelColour: "rgb(2,198,137)"

},

{

position: "right",

axisLabel: "Overdue Tickets",

axisLabelUseCanvas: true,

axisLabelColour: "#FF0000"

},

{

position: "right",

axisLabel: "Resolved Tickets",

axisLabelUseCanvas: true,

axisLabelColour: "#0062FF"

},

],

grid: {

hoverable: true //IMPORTANT! this is needed for tooltip to work

},

tooltip: true,

tooltipOpts: {

content: getTooltip

}

};

//var data3 = [[1420050600000, 6], [1422729000000, 5]];

// call the service to get the data in JSON format

flotService.getMonthlyTicketsSummary().then(function (results) {

// debugger;

var monthlyTicketsSummary = results.data;

var totalTickets = monthlyTicketsSummary[2].data;

var totalOverdueTickets = monthlyTicketsSummary[0].data;

var totalCompletedTickets = monthlyTicketsSummary[1].data;

var data6 = [];

var data7 = [];

var data8 = [];

// alert(new Date("2015-01-01").getTime())

for (j = 0; j < totalTickets.length; j++) {

var i = totalTickets[j].toString();

data5 = i.split(",");

data6 = data6 + "[" + new Date(data5[0]).getTime() + "," + data5[1] + "]" + ","

//data6[j] = "[5,10]"

}

data6 = JSON.parse("[" + data6.substring(0, data6.length - 1) + "]");

for (j = 0; j < totalOverdueTickets.length; j++) {

var i = totalOverdueTickets[j].toString();

data5 = i.split(",");

data7 = data7 + "[" + new Date(data5[0]).getTime() + "," + data5[1] + "]" + ","

//data6[j] = "[5,10]"

}

data7 = JSON.parse("[" + data7.substring(0, data7.length - 1) + "]");

for (j = 0; j < totalCompletedTickets.length; j++) {

var i = totalCompletedTickets[j].toString();

data5 = i.split(",");

data8 = data8 + "[" + new Date(data5[0]).getTime() + "," + data5[1] + "]" + ","

//data6[j] = "[5,10]"

}

data8 = JSON.parse("[" + data8.substring(0, data8.length - 1) + "]");

// set the data to be plotted on different y axes

$scope.dataset = [{

data: data6, label: 'Total Tickets', color: "rgb(2,198,137)", bars: {

show: true,

barWidth: 24 * 60 * 60 * 6000,

lineWidth: 1,

align: "center",

}

},

{

data: data7, label: ['Total Overdue Tickets'], yaxis: 2, color: "#FF0000", lines: {

show: true,

},

points: { fillColor: "#FF0000", symbol: "triangle", show: true, }

},

{

data: data8, label: ['Total Resolved Tickets'], yaxis: 3, color: "#0062FF", lines: {

show: true,

},

points: { fillColor: "#0062FF", symbol: "diamond", show: true, }

},

];

}

, function (error) {

alert(error.data);

}

);

}]);

现在一切就绪,我们只需运行我们的 API 项目,然后从 Visual Studio 运行 Angular 项目。

关注点

我真的不得不花时间来弄清楚如何将我从 JSON 中获取的日期转换为 Flot 库理解的格式。

 

© . All rights reserved.