I am trying to make a timeline chart using Google Charts and having a few issues I will detail below.
I started with an extremely simple example and then am trying to convert this to use an Ajax call to populate the chart.
To start I used a simple implementation with a hardcoded single line of data that works just fine.
google.charts.load("current", { packages: ["timeline"] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var container = document.getElementById('CurrentOrders');
var chart = new google.visualization.Timeline(container);
var data = new google.visualization.DataTable();
data.addColumn({ id: 'OrderNum', label: 'Order Number', type: 'string' });
data.addColumn({ id: 'PN', label: 'Part Number', type: 'string' });
data.addColumn({ id: 'StartDate', label: 'Start', type: 'date' });
data.addColumn({ id: 'EndDate', label: 'End', type: 'date' });
data.addRows([
['M12345', 'MyPartNumber', new Date(2023, 1, 4), new Date(2023, 1, 6)]
]);
var options = {
timeline: {
groupByRowLabel: true
}
};
chart.draw(data, options);
}
Next I created a Webmethod that returns the same dataset.
<System.Web.Services.WebMethod>
Public Shared Function GetOrders() As String
Dim mOrder As List(Of Morder) = New List(Of Morder)()
Dim constr As String = ConfigurationManager.ConnectionStrings("HYDMCS").ConnectionString
Dim Query As String = "SELECT TOP(1) OrderNumber,Part_Number, CONVERT(DATE,GETDATE()) AS StartDate, CONVERT(DATE,DATEADD(DAY,2,GETDATE())) AS EndDate, MfgDueDate FROM HYD_GP_ProductionSchedule ORDER BY Part_Number DESC "
Using con As New SqlConnection(constr)
Try
con.Open()
Using sqlCmd As SqlCommand = New SqlCommand(Query, con)
Using reader As SqlDataReader = sqlCmd.ExecuteReader
While reader.Read
If reader.HasRows Then
mOrder.Add(New Morder() With {
.OrderNum = reader(0).ToString(),
.PN = reader(1).ToString(),
.StartDate = reader(2),
.EndDate = reader(3)
})
End If
End While
End Using
End Using
con.Close()
Catch ex As Exception
If con.State = ConnectionState.Open Then
con.Close()
End If
End Try
End Using
Dim js As JavaScriptSerializer = New JavaScriptSerializer()
Return js.Serialize(mOrder)
End Function
It returns a result as expected.
[{"OrderNum":"M531270 ","PN":"VXLD0500510 C ","StartDate":"/Date(1704344400000)/","EndDate":"/Date(1704517200000)/"}]
However when trying to consume the results I have several issues. First the code.
google.charts.load("current", { packages: ["timeline"] });
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
$.ajax(
{
type: 'POST',
dataType: 'JSON',
contentType: 'application/json',
url: 'PlannersWorkBench.aspx/GetOrders',
success:
function (response) {
drawGraph(response.d);
}
});
};
// Callback that creates and populates a data table,
function drawGraph(dataValues) {
// Initialization.
var data = new google.visualization.DataTable();
// Setting.
data.addColumn({ id: 'OrderNum', label: 'Order Number', type: 'string' });
data.addColumn({ id: 'PN', label: 'Part Number', type: 'string' });
data.addColumn({ id: 'StartDate', label: 'Start', type: 'date' });
data.addColumn({ id: 'EndDate', label: 'End', type: 'date' });
// Processing.
for (var i = 0; i < dataValues.length; i++) {
// Setting.
data.addRow([dataValues[i].OrderNum, dataValues[i].PN, dataValues[i].StartDate, dataValues[i].EndDate]);
//data.addRow(['M1', 'PN1', new Date(2023, 1, 4), new Date(2023, 1, 6)]);
}
// Instantiate and draw our chart, passing in some options.
var container = document.getElementById('CurrentOrders');
var chart = new google.visualization.Timeline(container);
// Draw chart.
var options = {
timeline: {
groupByRowLabel: true
}
};
chart.draw(data, options);
}
The first and formost issue is that I do not get a chart, just an error.
When trying to troubleshoot I hardcoded the row value to insert to see if the JSON response is the issue.
If I change..
for (var i = 0; i < dataValues.length; i++) {
// Setting.
data.addRow([dataValues[i].OrderNum, dataValues[i].PN, dataValues[i].StartDate, dataValues[i].EndDate]);
}
to
for (var i = 0; i < dataValues.length; i++) {
// Setting.
data.addRow(['M1', 'PN1', new Date(2023, 1, 4), new Date(2023, 1, 6)]);
}
I do see a change, however there are still issues. If you look at the screenshot below you can see that the order number is not visible, also there are 136 rows in the chart. For whatever reason dataValues.length=136 even though I am only getting one result from the Webmethod.
Any advice would be great or a working example. Thanks in advance for any help!
Two items were needed to correct this.
While I can't find any documentation detailing this the data needs to be parsed before looping through it to grab the values.
The original code:
var data = new google.visualization.DataTable();
// Setting.
data.addColumn({ id: 'OrderNum', label: 'Order Number', type: 'string' });
data.addColumn({ id: 'PN', label: 'Part Number', type: 'string' });
data.addColumn({ id: 'StartDate', label: 'Start', type: 'date' });
data.addColumn({ id: 'EndDate', label: 'End', type: 'date' });
// Processing.
for (var i = 0; i < dataValues.length; i++) {
// Setting.
data.addRow([dataValues[i].OrderNum, dataValues[i].PN, dataValues[i].StartDate, dataValues[i].EndDate]);
}
Was changed to..
var data = new google.visualization.DataTable();
// Setting.
data.addColumn({ id: 'OrderNum', label: 'Order Number', type: 'string' });
data.addColumn({ id: 'PN', label: 'Part Number', type: 'string' });
data.addColumn({ id: 'StartDate', label: 'Start', type: 'date' });
data.addColumn({ id: 'EndDate', label: 'End', type: 'date' });
// Processing.
parsedData = JSON.parse(dataValues);
for (var i = 0; i < parsedData.length; i++) {
//Setting.
data.addRow([parsedData[i].OrderNum, parsedData[i].PN, new Date(parsedData[i].StartDate), new Date(parsedData[i].EndDate)]);
}
Note the parsedData variable.
Next issue was the JSON formatting on the date field. According to Google documentation when using JSON the date needs to come over as a string.
"Using the Date constructor is useful when manually constructing your DataTable using the addColumn(), addRow(), and addRows() methods, as well as the arrayToDataTable() method. However, if using JSON to specify data, the string representation needs to be used."
That being said the data type for the date fields was changed to a string and formatted properly in SQL in my query.