Rendering HighCharts in AngularJS from Json Object - angularjs

Learning AngularJS and HighCharts.
[Plunker Link][1]
I would like to understand how I can get the data from a JSON object and dynamically update the values on the x-axis and the bar chart value. The Y-axis values are constant.
Right now I have hard coded the values, I want the x-axis and bar chart values from the backend.
Here is what I have tried -
(function() {
'use strict';
angular.module('myModule', [])
// Directive for generic chart, pass in chart options
.directive('hcChart', function() {
return {
restrict: 'E',
template: '<div></div>',
scope: {
options: '='
},
link: function(scope, element) {
Highcharts.chart(element[0], scope.options);
}
};
})
.controller('MainCtrl', function($scope, $http) {
$scope.chartData = [];
$scope.totalCostList = [];
loadChartData();
function loadChartData() {
var httpRequest = $http({
method: 'GET',
url: './example.json'
}).then(function(response) {
console.log(response.data);
$scope.chartData = response.data;
console.log("length:" + $scope.chartData.activityResponse.length);
for (var i = 0; i < $scope.chartData.activityResponse.length; i++) {
$scope.totalCostList.push(parseInt($scope.chartData.activityResponse[i].totalCost));
}
console.log($scope.totalCostList);
});
}
//var chartData = $scope.totalCostList;
var yAxisLabels = [1, 5000, 10000, 15000, 20000];
var chartData = [
10000, 5000, 4000, 15000, 16000, 10000, 5000, 4000, 15000, 2000,
10000, 5000, 4000, 15000, 16000, 10000, 5000, 4000, 15000, 2000,
10000, 5000, 4000, 15000, 16000, 10000, 5000, 4000, 15000, 2000,
10000, 5000, 4000, 15000, 16000, 10000, 5000, 4000, 15000, 2000,
10000, 5000, 4000, 15000, 16000, 10000, 5000, 4000, 15000, 2000,
10000, 5000
];
var dateLine = Date.UTC(2015, 0, 1);
Highcharts.getOptions().colors[0] = {
linearGradient: {
x1: 0,
y1: 0,
x2: 0,
y2: 1
},
stops: [
[0, '#6EB7D8'],
[0.4, '#2989D8'],
[0.7, '#207cca'],
[1, '#1E5799']
]
};
Highcharts.setOptions({
lang: {
thousandsSep: ','
}
});
//To give the chart a bounce effect
Math.easeOutBounce = function(pos) {
if ((pos) < (1 / 2.75)) {
return (7.5625 * pos * pos);
}
if (pos < (2 / 2.75)) {
return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);
}
if (pos < (2.5 / 2.75)) {
return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);
}
return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);
};
$scope.chartOptions = {
chart: {
type: 'column',
margin: [70, 30, 30, 80]
},
exporting: {
enabled: false
},
credits: {
enabled: false
},
legend: {
enabled: false
},
title: {
text: 'Weekly Inventory at Cost',
style: {
color: '#333'
},
align: 'left',
x: 10,
y: 20
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
month: '%b'
},
lineColor: '#333',
tickColor: '#333',
crosshair: true,
startOnTick: false,
endOnTick: false,
minPadding: 0,
maxPadding: 0,
tickmarkPlacement: 'on',
labels: {
align: 'left',
rotation: 0
}
},
yAxis: {
crosshair: true,
lineColor: '#333',
tickColor: '#333',
tickPositioner: function() {
return yAxisLabels;
},
labels: {
format: '{value:,.0f}'
},
title: {
enabled: false
},
lineWidth: 1,
tickWidth: 1,
id: 'cost',
gridLineWidth: 0,
min: 1
},
plotOptions: {
column: {
pointPadding: 0.1,
borderWidth: 0,
pointPlacement: 'between'
}
},
shadow: true,
series: [{
data: chartData,
pointStart: dateLine,
pointInterval: 7 * 24 * 3600 * 1000 // 7days
}]
};
});
})();
<!DOCTYPE html>
<html ng-app="myModule">
<head>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<hc-chart options="chartOptions" style="width: 96%; height: 300px;">Placeholder for generic chart</hc-chart>
</body>
</html>
My example JSON -
{"message": "success",
"status": "OK",
"activityResponse": [{
"storeNo": "00208",
"wk": "1",
"year": "2016",
"totalCost": "349622.9"
},{
"storeNo": "00208",
"wk": "2",
"year": "2016",
"totalCost": "2000"
},
{
"storeNo": "00208",
"wk": "3",
"year": "2016",
"totalCost": "15000"
}]
}

Here is an approach to adding to the x-axis categories and updating the category values. Grab a reference to the chart's series when the chart is created.
var series = this.series[0];
Then, when there is an update to the data, make the following call.
series.setData(seriesDataSource, true, true, false);
I have adapted your Plunker to show an example of the chart with series records being added and updated.
https://embed.plnkr.co/SWGuRTyTM3AU6yhptYvM/

Related

Highcharts column chart with target and color gradient

Is below chart possible in highchart
Column with high, low and target
Color gradient with denser on target and lighter away
Data table for low, high and target
Managed to get some bits, but not full functionality
https://jsfiddle.net/z9u5hgod/2/
TIA
[
{
type: 'bullet',
dataLabels: [
{ format: '{point.y}' } ,
{format: '{point.target}',
inside: true},
{
inside: true,
verticalAlign: 'bottom',
align: 'center',
format: '{point.low}'
}
],
data: [
{
low: 250,
y: 1650,
target: 750,
color: {
linearGradient: [0, '70%', 0, '50%'],
stops: [
[0, 'green'],
[1, 'orange']
]
}
},
{
low: 100,
y: 2000,
target: 1500
}
]
},
{
data: [{
low: 600,
y: 2350,
target: 2100
}, {
low: 450,
y: 1700,
target: 1250
}]
}]
Response from higcharts developer
https://jsfiddle.net/BlackLabel/xbvp8he7/
const chart = Highcharts.chart('container', {
chart: {
type: 'bullet',
events: {
load() {
const firstSeries = this.series[0];
firstSeries.data.forEach(point => {
const {
low,
y,
target
} = point,
gradientPoint = (y - target) / (y - low);
point.update({
color: {
linearGradient: {
x1: 0,
x2: 0,
y1: 0,
y2: 1
},
stops: [
[0, 'blue'],
[gradientPoint, 'purple'],
[1, 'blue']
],
}
})
})
}
}
},
plotOptions: {
series: {
pointPadding: 0.2,
groupPadding: 0.1,
targetOptions: {
borderWidth: 0,
height: 3,
color: 'red',
width: '100%'
}
}
},
xAxis: {
categories: ['Alex ar', 'Cairo ar']
},
series: [
{
type: 'bullet',
dataLabels: [{
enabled: true,
}, {
enabled: true,
verticalAlign: 'top',
align: 'center',
color: 'white',
useHTML: true,
formatter() {
const point = this.point,
target = point.targetGraphic,
targetY = target.getBBox().y - point.shapeArgs.y - 25;
return `
<div class="datalabelInside" style="position: relative; top: ${targetY}px">${point.target}</div>
`;
}
}, {
verticalAlign: 'bottom',
inside: true,
y: 20,
format: '{point.low}',
enabled: true
}, ],
data: [{
low: 250,
y: 1650,
target: 750
},
{
low: 100,
y: 2000,
target: 1500
}
]
},
{
data: [{
low: 600,
y: 2350,
target: 2100
}, {
low: 450,
y: 1700,
target: 1250
}]
}
],
tooltip: {
pointFormat: '<b>{point.y}</b> (with target at {point.target})'
}
});

How to set X coordinate for each bar with react chart js 2?

I want to make a chart with min and max vertical lines and bars between them. I can't find information how to set bars' X coordinate or make custom line plot with vertical 'bars' instead of points.
And also I don't understand how to scale X axis, why MAX is left-side MIN? Min=22.5, Max=24.5
let plot_options = {
showScale: true,
pointDot: true,
showLines: true,
maintainAspectRatio: false,
annotation: {
annotations: [
{
type: 'line',
mode: 'vertical',
scaleID: 'y-axis-0',
value: min,
borderColor: 'red',
borderWidth: 2,
label: {
backgroundColor: 'red',
content: 'Min',
enabled: true,
},
},
{
type: 'line',
mode: 'vertical',
scaleID: 'y-axis-0',
value: max,
borderColor: 'red',
borderWidth: 2,
label: {
backgroundColor: 'red',
content: 'MAX',
enabled: true,
},
},
]
},
title: {
display: true,
text: plotHeader,
},
responsive: true,
legend: {
display: false,
},
scales: {
xAxes: [{
scaleLabel: {
display: true,
labelString: labelx
},
ticks: {
min: min,
max: max
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: labely
},
ticks: {
beginAtZero: true,
},
}]
},
}
data = {
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
labels: labels,
datasets: [{
data: values,
borderColor: BLUE,
backgroundColor: BLUE
}]
}
<Bar options={plot_options} data={data} plugins={ChartAnnotation} />
That's what I expect:
This solution is based on this answer for the positioning of the bars on a linear x-axis.
You can further use the Plugin Core API to draw the vertical min and max lines with their labels directly on the canvas. The API offers a number of hooks that can be used to perform custom code. In your case, you could use the afterDraw hook together with CanvasRenderingContext2D.
Please take a look at the runnable code below and see how it works. It should not be too hard to make similar code work with react-chartjs-2.
new Chart("chart", {
type: 'bar',
plugins: [{
afterDraw: chart => {
let ctx = chart.chart.ctx;
ctx.save();
let xAxis = chart.scales['x-axis-0'];
let yAxis = chart.scales['y-axis-0'];
let dataset = chart.data.datasets[0];
[dataset.min, dataset.max].forEach((v, i) => {
var x = xAxis.getPixelForValue(+v * 1000);
ctx.fillStyle = 'red';
ctx.font = '14px Arial';
ctx.textAlign = 'center';
ctx.fillText(i == 0 ? 'Min' : 'Max', x, yAxis.top + 14);
ctx.fillStyle = 'gray';
ctx.font = '12px Arial';
ctx.fillText(v, x, yAxis.bottom + 20);
ctx.beginPath();
ctx.moveTo(x, yAxis.top + 20);
ctx.strokeStyle = 'red';
ctx.lineTo(x, yAxis.bottom + 3);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
datasets: [{
min: 22.5,
max: 24.5,
data: [
{ x: '22.83', y: 18 },
{ x: '23.17', y: 15 },
{ x: '23.44', y: 13 },
{ x: '24.32', y: 20 }
],
borderColor: 'blue',
backgroundColor: 'blue',
barThickness: 20
}]
},
options: {
legend: {
display: false,
},
scales: {
xAxes: [{
offset: true,
type: 'time',
time: {
parser: 'X',
unit: 'millisecond',
displayFormats: {
millisecond: 'X'
}
},
ticks: {
source: 'data',
min: '22.5',
callback: (v, i, values) => values[i].value / 1000
},
gridLines: {
display: false
},
}],
yAxes: [{
ticks: {
beginAtZero: true,
max: 22,
stepSize: 2
}
}]
}
}
});
canvas {
max-width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="chart" height="200"></canvas>

Highcharts. How to start areaspline chart from start y axis?

I am new to highcharts so i might be missing something here.
Recently i was working on area chart and i was able to draw the chart and everything is perfect, But i have a requirement where i have area chart should start from x as 0. Is there any way to do this ? I have attached a screenshot and fiddle link.
Here is fiddle link: https://jsfiddle.net/shantanugade/9vwxm412/
Highcharts.chart('container', {
chart: {
type: 'area'
},
title: {
text: 'US and USSR nuclear stockpiles'
},
xAxis: {
allowDecimals: false,
labels: {
formatter: function () {
return this.value; // clean, unformatted number for year
}
},
accessibility: {
rangeDescription: 'Range: 1940 to 2017.'
}
},
yAxis: {
title: {
text: 'Nuclear weapon states'
},
labels: {
formatter: function () {
return this.value / 1000 + 'k';
}
}
},
tooltip: {
pointFormat: '{series.name} had stockpiled <b>{point.y:,.0f}</b><br/>warheads in {point.x}'
},
plotOptions: {
area: {
pointStart: 1940,
marker: {
enabled: false,
symbol: 'circle',
radius: 2,
states: {
hover: {
enabled: true
}
}
}
}
},
series: [{
name: 'USA',
data: [
null, null, null, null, null, 6, 11, 32, 110, 235,
369, 640, 1005, 1436, 2063, 3057, 4618, 6444, 9822, 15468,
20434, 24126, 27387, 29459, 31056, 31982, 32040, 31233, 29224, 27342,
26662, 26956, 27912, 28999, 28965, 27826, 25579, 25722, 24826, 24605,
24304, 23464, 23708, 24099, 24357, 24237, 24401, 24344, 23586, 22380,
21004, 17287, 14747, 13076, 12555, 12144, 11009, 10950, 10871, 10824,
10577, 10527, 10475, 10421, 10358, 10295, 10104, 9914, 9620, 9326,
5113, 5113, 4954, 4804, 4761, 4717, 4368, 4018
]
}, {
name: 'USSR/Russia',
data: [ 1605, 2471, 3322, 4238, 5221, 6129, 7089, 8339, 9399, 10538,
5000, 2500, 500, 1200, 1500, 2000, 4260, 6600, 8690, 10600,
1605, 2471, 3322, 4238, 5221, 6129, 7089, 8339, 9399, 10538,
11643, 13092, 14478, 15915, 17385, 19055, 21205, 23044, 25393, 27935,
30062, 32049, 33952, 35804, 37431, 39197, 45000, 43000, 41000, 39000,
37000, 35000, 33000, 31000, 29000, 27000, 25000, 24000, 23000, 22000,
21000, 20000, 19000, 18000, 18000, 17000, 16000, 15537, 14162, 12787,
12600, 11400, 5500, 4512, 4502, 4502, 4500, 4500
]
}] })
As You can see in the image there is small gap.
You need to reduce xAxis.minPadding property:
xAxis: {
minPadding: 0,
...
}
Live demo: https://jsfiddle.net/BlackLabel/k2mzg0yq/
API Reference: https://api.highcharts.com/highcharts/xAxis.minPadding

Integrating Highcharts Sparkline with Angular JS UI Grid

I am trying to integrate highcharts sparkline with angular ui-grid directive but unable to plot the sparkline. When we try to dynamically plot the sparklines using ui-grid nothing gets plotted. I have made necessary changes to the sparkline code as well yet unable to find what is the issue. We need age column to have highcharts sparkline. Any pointer will be of great help.
$scope.gridOptions = {
enableFiltering: false,
enableSorting: true,
}
$scope.gridOptions.columnDefs = [{
name: 'id'
}, {
name: 'name'
}, {
name: 'age',
cellTemplate: '<div id="table-sparkline" data-sparkline="71, 78, 39, 66"></div>'
}, {
name: 'address.city'
}];
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.success(function(data) {
$scope.gridOptions.data = data;
console.log(JSON.stringify(data));
/**
* Create a constructor for sparklines that takes some sensible defaults and merges in the individual
* chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine').
*/
Highcharts.SparkLine = function(a, b, c) {
var hasRenderToArg = typeof a === 'string' || a.nodeName,
options = arguments[hasRenderToArg ? 1 : 0],
defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 120,
height: 20,
style: {
overflow: 'visible'
},
// small optimalization, saves 1-2 ms each sparkline
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
title: {
text: null
},
startOnTick: false,
endOnTick: false,
tickPositions: []
},
yAxis: {
endOnTick: false,
startOnTick: false,
labels: {
enabled: false
},
title: {
text: null
},
tickPositions: [0]
},
legend: {
enabled: false
},
tooltip: {
backgroundColor: null,
borderWidth: 0,
shadow: false,
useHTML: true,
hideDelay: 0,
shared: true,
padding: 0,
positioner: function(w, h, point) {
return {
x: point.plotX - w / 2,
y: point.plotY - h
};
}
},
plotOptions: {
series: {
animation: false,
lineWidth: 1,
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
marker: {
radius: 1,
states: {
hover: {
radius: 2
}
}
},
fillOpacity: 0.25
},
column: {
negativeColor: '#910000',
borderColor: 'silver'
}
}
};
options = Highcharts.merge(defaultOptions, options);
return hasRenderToArg ?
new Highcharts.Chart(a, options, c) :
new Highcharts.Chart(options, b);
};
var start = +new Date(),
$tds = $('div[data-sparkline]'),
fullLen = $tds.length,
n = 0;
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length,
$td,
stringdata,
arr,
data,
chart;
for (i = 0; i < len; i += 1) {
$td = $($tds[i]);
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = $.map(arr[0].split(', '), parseFloat);
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('div').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
n += 1;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
}
}
doChunk();
Plunker

Set background color of Angular-nvD3

I am using Angular-nvD3 in my Charts and I would like to change the background of this chart like the picture example. Can anyone help me please?
Here its the HTML code:
<div class="col-md-6">
<nvd3 options="optionsrigidez" data="datarigidez" class="with-3d-shadow with-transitions"></nvd3>
</div>
And here its the angular params:
1. Options:
$scope.optionsrigidez = {
chart: {
type: 'lineChart',
height: 250,
reduceXTicks: true, // if false a tick will show for every data point
margin: {
top: 20,
right: 20,
bottom: 40,
left: 55
},
x: function (d) { return d.x; },
y: function (d) { return d.y; },
useInteractiveGuideline: true,
dispatch: {
stateChange: function (e) { console.log("stateChange"); },
changeState: function (e) { console.log("changeState"); },
tooltipShow: function (e) { console.log("tooltipShow"); },
tooltipHide: function (e) { console.log("tooltipHide"); }
},
yDomain: [0.0, 100.0],
showLegend: false,
xAxis: {
axisLabel: 'Data da análise',
tickFormat: function (d) {
return daysOfReport[d];
},
rotateLabels: -1
},
yAxis: {
axisLabel: 'kV',
tickFormat: function (d) {
return d3.format('.01f')(d);
},
axisLabelDistance: -10
},
callback: function (chart) {
//console.log("!!! lineChart callback !!!");
}
},
title: {
enable: true,
text: 'Rigidez Dielétrica - Calota'
},
caption: {
enable: true,
html: '<b>Gráfico 3.</b> É uma medida da capacidade do óleo resistir à solicitação elétrica. Revela também a presença de impurezas polares como a água e outros oxigenados e sólidos (NBR 6869). Fonte: <a href="http://www.filtroil.ind.br/analise-de-oleo-isolante">Filtroil.<a/>',
css: {
'text-align': 'justify',
'margin': '10px 13px 0px 7px'
}
}
};
Data:
function rigidez_function() {
var rigidez = [];
for (var i = 0; i < $scope.RelatorioOleo_analisesFQ.length; i++) {
rigidez.push({ x: i, y: $scope.RelatorioOleo_analisesFQ[i].calota });
}
//Line chart data should be sent as an array of series objects.
return [
{
values: rigidez, //values - represents the array of {x,y} data points
key: 'Rigidez Dielétrica', //key - the name of the series.
color: '#5A5A5A', //color - optional: choose your own line color.
strokeWidth: 2,
//classed: 'dashed'
}
];
};
$scope.datarigidez = rigidez_function();
Probably a bit late, but yes you can!
You have to create a MultiChart and draw the colored zones as 'stacked areas'. I've created a plunk here: http://plnkr.co/hW3Anw
chart: {
type: 'multiChart',
height: 450,
margin : {
top: 30,
...
testdata[1].type = "area"
testdata[1].yAxis = 1
testdata[1].values = [{x: 0, y: -0.5}, {x: 55, y: -0.5}]
testdata[2].type = "area"
testdata[2].yAxis = 1
testdata[2].values = [{x: 0, y: -5}, {x: 55, y: -5}]
...

Resources