I'm evaluating Highcharts and I'm struggling to format my axes and data labels correctly. On the tooltip object for a series I can set the prefix, suffix and decimals ( this is wonderful ). I cannot find similar options for data labels and the axes?
What is the correct way to format the axis, tooltips and labels to all use the correct prefix, suffix, decimals and use a comma for the thousands separator? Is there a single place this can be set to be inherited?
I have tried using a formatter on data labels but I've been unable to implement it as it does not know what "this" is.
Below is my example using a new angular 14 project:
Thank you
import { Component, OnInit } from '#angular/core';
import { SeriesColumnOptions, SeriesLineOptions } from 'highcharts';
import * as Highcharts from 'highcharts';
#Component({
selector: 'app-format',
template: '<highcharts-chart [Highcharts]="Highcharts" [options]="options" style="width: 100%; height: 400px; display: block;"></highcharts-chart>'
})
export class FormatComponent implements OnInit {
Highcharts = Highcharts;
options!: Highcharts.Options;
constructor() {
}
ngOnInit(): void {
this.options = {
title: {
text: ''
},
xAxis: {
title: {
text: 'xAxis'
},
categories: ['Cat A', 'Cat B', 'Cat C', 'Cat D', 'Cat E']
},
yAxis: [
{
title: {
text: 'currency axis'
}
},
{
title: {
text: 'percent axis'
},
opposite: true
}
],
series: []
};
const currencySeries: SeriesColumnOptions = {
type: 'column',
name: 'Currency',
data: [123.45, 4324.12, 17245.23, 123.5, 13453.4],
dataLabels: {
enabled: true
},
tooltip: {
valuePrefix: '£',
valueDecimals: 2
}
};
this.options.series?.push(currencySeries);
const percentSeries: SeriesLineOptions = {
type: 'line',
name: 'Percent',
data: [34.1, 62, 82.3, 76.6, 12.3, 99],
yAxis: 1,
dataLabels: {
enabled: true
},
tooltip: {
valueSuffix: '%',
valueDecimals: 1
}
};
this.options.series?.push(percentSeries);
}
}
To format axis labels check xAxis.labels.format, datalabels units or custom formating you can set in dataLabels.format, also recomended options is use callback formatter().
"This" depending on where it is called, refers to an axis or a series.
Highcharts.chart('container', {
xAxis: {
labels: {
formatter: function() {
let label = this.axis.defaultLabelFormatter.call(this);
console.log('xAxis this:', this);
return label;
}
}
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, ],
pointStart: 9000,
type: 'column',
dataLabels: {
enabled: true,
formatter: function() {
console.log('datalabels this:', this);
return this.y;
}
}
}]
});
Demo: https://jsfiddle.net/BlackLabel/vam2t5hw/
Related
I have a highchart line chart which currently displayed in bootstrap 4 card.
I want it to displayed full screen, which I'm currently aware that highchart 6.2.0 has option to enabled exporting file, so that I can use the exporting context menu. so, I enabled them but "showFullscreen" option not showing in the exporting context menu.
I imported highchart and exporting module to the component.
in the documentation highchart guys says that I have to include viewFullscreen as string to the menuItems array. I also did that. but nothing work.
import { chart } from 'highcharts';
import * as Highcharts from 'highcharts/highcharts';
import * as HighchartsMore from 'highcharts/highcharts-more';
import * as HighchartsSolidGauge from 'highcharts/modules/solid-gauge';
import * as HighChartExport from 'highcharts/modules/exporting';
HighchartsMore(Highcharts);
HighchartsSolidGauge(Highcharts);
HighChartExport(Highcharts);
#Component({
selector: 'app-line-chart',
templateUrl: './line-chart.component.html',
styleUrls: ['./line-chart.component.css']
})
export class LineChartComponent implements OnInit, OnChanges {
#ViewChild('chartTarget') chartTarget: ElementRef;
#Input() data;
#Input() lineColor;
options: any;
chart: Highcharts.ChartObject;
constructor() { }
ngOnInit() {
this.drawLineChart();
}
ngOnChanges(changes: SimpleChanges) {
if (this.chart && changes['data']) {
this.drawLineChart();
}
}
drawLineChart() {
this.options = {
chart: {
scrollablePlotArea: {
minWidth: 700
},
height: 230,
zoomType: 'x'
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
gridLineWidth: 1,
/*tickInterval: 7 * 24 * 3600 * 1000, // one week
tickWidth: 0,*/
labels: {
align: 'left',
x: 3,
y: -3,
enabled: false
}
},
yAxis: [{ // left y axis
title: {
text: null
},
padding: 3,
showFirstLabel: false,
gridLineWidth: 1,
/*labels: {
align: 'left',
x: -10
}*/
}],
colors: this.lineColor,
legend: {
align: 'left',
verticalAlign: 'bottom',
borderWidth: 0
},
tooltip: {
shared: true,
crosshairs: true,
headerFormat: ''
},
exporting: {
enabled: true,
menuItemDefinitions: {
// Custom definition
},
buttons: {
contextButton: {
menuItems: ['viewFullscreen']
}
}
},
plotOptions: {
series: {
cursor: 'pointer',
marker: {
enabled: false
}
}
},
series: this.data
};
this.chart = chart(this.chartTarget.nativeElement, this.options as any);
}
}
I followed this link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/exporting/menuitemdefinitions/
but when I clicked that hamburger icon every other options showing except "viewFullscreen" option didn't work.
To add a custom button to context menu you have to add it to exporting.menuItemDefinitions and also exporting.buttons.contextButton.menuItems array. Note, that fullscreen requires an additional module to be loaded: modules/full-screen.
Code:
Highcharts.chart('container', {
exporting: {
menuItemDefinitions: {
fullscreen: {
onclick: function() {
Highcharts.FullScreen.prototype.init(this.renderTo);
},
text: 'Full screen'
}
},
buttons: {
contextButton: {
menuItems: ['downloadPNG', 'downloadSVG', 'separator', 'fullscreen']
}
}
},
series: [{
data: [
43934,
52503,
57177,
69658,
97031,
119931,
137133,
154175
]
}],
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/full-screen.js"></script>
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/qydgxs12/
Angular demo:
https://codesandbox.io/s/73lomvnqk0
API reference:
https://api.highcharts.com/highcharts/exporting.buttons.contextButton.menuItems
https://api.highcharts.com/highcharts/exporting.menuItemDefinitions
I want create a bar line graphs with navigator,range selector, y axis from both side and graph sector. I implement it using Highcharts.Chart() but it's x-axis not comes properly. when i create x-axis properly after change categories to ["2017-2-3'] then range selector goes to 1970 (default value) so i convert date to milliseconds. Now in the x-axis have unwanted values. I want to show only x-axis values which shows in category array. currently 1m,3m,6m not worked i think it happen because of this x-axis issue.
jsfiddle : http://jsfiddle.net/m05sgk3j/1/
$(document).ready(function() {
var categories = [1551420000000,1549000800000,1546322400000,1543644000000,1541052000000, 1538373600000, 1535781600000,1533103200000, 1530424800000, 1527832800000, 1525154400000, 1522562400000, 1519884000000, 1517464800000,1514786400000];
new Highcharts.Chart({
chart: {
renderTo: 'container'
},
title: {
text: 'In March 2019, the average CT_HOURS is 10.55 hours.'
},
rangeSelector: {
enabled: true,
buttons: [{
type: 'millisecond',
count: 1,
text: '1m'
}, {
type: 'millisecond',
count: 3,
text: '3m'
}, {
type: 'millisecond',
count: 6,
text: '6m'
}, {
type: 'all',
text: 'All'
}],
selected: 4,
inputDateFormat: '%Y-%m-%d',
inputEditDateFormat: '%Y-%m-%d'
},
navigator: {
enabled: true,
xAxis: {
tickInterval: 15,
labels: {
/* formatter: function() {
return categories[this.pos]
} */
}
}
},
scrollbar: {
enabled: true
},
xAxis: {
// categories: categories,
type: 'datetime',
tickInterval : 2,
// tickInterval: {_tickInterval},
/* labels: {
step:10
}, */
/* maxZoom: 30 * 24 * 3600000, */
dateTimeLabelFormats : {
day: '%Y-%m'
}
// crosshair: true,
// minRange: 1
},
yAxis: [{ // Primary yAxis
labels: {
format: '{value}h',
style: {
color: Highcharts.getOptions().colors[1]
}
},
title: {
text: 'AVERAGE CT_HOURS',
style: {
color: Highcharts.getOptions().colors[1]
}
}
}, { // Secondary yAxis
title: {
text: 'REQUEST COUNT',
style: {
color: Highcharts.getOptions().colors[0]
}
},
labels: {
format: '{value}',
style: {
color: Highcharts.getOptions().colors[0]
}
},
opposite: true
}],
series: [{
name: 'REQUEST COUNT',
type: 'column',
yAxis: 1,
data: [
[1551420000000, 49.9],
[1549000800000, 71.5],
[1546322400000, 106.4],
[1543644000000, 129.2],
[1541052000000, 144.0],
[1538373600000, 176.0],
[1535781600000, 135.6],
[1533103200000, 148.5],
[1530424800000, 49.9],
[1527832800000, 71.5],
[1525154400000, 106.4],
[1522562400000, 129.2],
[1519884000000, 144.0],
[1517464800000, 176.0],
[1514786400000, 135.6]
],
tooltip: {
valueSuffix: ''
}
}, {
name: 'AVERAGE CT_HOURS',
type: 'spline',
data: [[1551420000000, 56.6],
[1549000800000, 46.3],
[1546322400000, 32.8],
[1543644000000, 43.4],
[1541052000000, 40.8],
[1538373600000, 43.0],
[1535781600000, 43.1],
[1533103200000, 44.6],
[1530424800000, 45.7],
[1527832800000, 27.8],
[1525154400000, 39.9],
[1522562400000, 29.3],
[1519884000000, 27.9],
[1517464800000, 27.4],
[1514786400000, 17.6]],
tooltip: {
valueSuffix: 'h'
}
}]
});
});
Just comment the tickInterval for the xAxis
//tickInterval : 2,
Fiddle
First of all, you have unsorted data. If you want to invert your data, use reversed option.
Also, the rangeSelector and the tickInterval are wrong. If you use datetime axis, then the basic unit is one millisecond.
However, to show dates only from the categories array, use the tickPositions option and formatter function for labels:
xAxis: {
reversed: true,
minRange: 1,
type: 'datetime',
tickPositions: categories,
labels: {
formatter: function() {
return Highcharts.dateFormat('%Y-%m', this.value);
}
}
},
Live demo: http://jsfiddle.net/BlackLabel/a6Lphq4k/
API Reference:
https://api.highcharts.com/highcharts/xAxis.reversed
https://api.highcharts.com/highcharts/xAxis.tickPositions
https://api.highcharts.com/highcharts/xAxis.labels.formatter
(1) First always make sure that you are injecting timestamps in your categories, and formatting them in :
(1-1) xAxis.labels.formatter function [for x axis labels]
(1-2) navigator.xAxis.labels.formatter function [for navigation labels format)
(2) Second make sure that you are clearing your (xAxis.categories) if you push data into it. because highcharts don't sort your array. if you just assign new array that's ok.
(3) Note : Based on values on your categories array, navigation gets some values like xAxis min and xAxis Max. when you change your data these values remain and that's why your navigation collapses. so when changing data make sure to update. you can use 0 for minimum of navigator and categories.length for maximum value of navigator.
you can access updated values also in dataMin and dataMax.
Hope this answer help you.
I'm looking to correct some y-Axis issues. I'm looking to remove, or edit, the left and right axis-labels and keep the middle one. [the 0 - 2400 label and remove, or edit, the 0-72g and 0-2400m]
In doing so, I also want to keep all the data intact, however not the labels.
here's my JSFiddle. https://jsfiddle.net/codkare17/L7w67znv/5/
function createChart() {
Highcharts.setOptions({
lang: {
thousandsSep: ','
}
});
Highcharts.stockChart('container', {
rangeSelector: {
selected: 4
},
yAxis: [{
labels: {
min: 0,
max: 8000
},
title: {
text: "Price (USD)",
formatter: '${value}'
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
}, {}, {}],
plotOptions: {
series: {
showInNavigator: false
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> <br/>',
valueDecimals: 2,
split: true
},
series: seriesOptions
});
}
$.getJSON('https://www.coincap.io/history/365day/BTC', function(json) {
console.log(json)
$.each(names, function(i, name) {
seriesOptions.push({
name: name,
data: json[name],
type: name === 'volume' ? 'column' : 'line',
yAxis: i
})
});
createChart()
});`
You can change yAxis' visible property to false: https://jsfiddle.net/kkulig/L7w67znv/6/
I am using highcharts to in my app and want to add tooltip with thousand separator like I did it in data labels. I used custom formatting for tooltip, so what should I change to achieve this
tooltip options in highcharts
tooltip: {
formatter: function () {
return (this.x + ':' + this.y);
},
shared: true,
useHTML: true
},
JS FIDDLE
use thousand separator in lang
$(function () {
Highcharts.setOptions({
lang: {
decimalPoint: '.',
thousandsSep: ','
}
});
and in tooltip- formatter use like
tooltip: {
pointFormat: '<b>{point.x} :</b>' + 'Count: <b>{point.y:,.0f}</b>',
shared: true,
useHTML: true
}
Updated fiddle with separator without decimal point
Just following Nishith Kant Chaturvedi's answer, and since there is no jsfiddle example available, here you can see how to implement that answer.
Highcharts.setOptions({
lang: {
decimalPoint: '.',
thousandsSep: ','
}
});
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: ''
},
xAxis: {
categories: ['Salary']
},
yAxis: {
title: {
text: ''
},
stackLabels: {
enabled: true,
format: '{total:,.2f} $us'
},
labels: {
format: "{value:,.2f} $us",
}
},
legend: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
format: '{point.y:,.2f} $us',
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
}
}
},
series: [{
type: 'column',
name: 'Tomas',
data: [60000]
}, {
type: 'column',
name: 'Amy',
data: [18000]
}, {
type: 'column',
name: 'Jenny',
data: [85000]
}]
});
http://jsfiddle.net/zrc5skLy/
Use Highcharts.numberFormat() in point.x or point.y
example:
tooltip: {
enabled: true,
split: true,
shared: true,
formatter: function () {
// The first returned item is the header, subsequent items are the points
return [Highcharts.dateFormat("%Y-%m-%d %H:%M:%S", this.x)].concat(
this.points
? this.points.map(function (point) {
return (
point.series.name +
": " +
// numberFormat(data, decimal)
Highcharts.numberFormat(point.y, 2)
);
})
: []
);
},
},
I have a chart that looks like this:
http://jsfiddle.net/rtGFm/37/
I would like to have a "sort" button that sorts high to low each category, putting the columns in a different order for each category. Is this possible with HighCharts?
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: ''
},
subtitle: {
text: ''
},
xAxis: {
categories: [
'foreclosures',
'nuisances',
'distance from city center'
]
},
yAxis: {
min: 0,
title: {
text: ''
}
},
tooltip: {
formatter: function() {
return ''+
this.x +': '+ this.y +' mm';
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{
name: 'Alger Heights',
data: [49.9, 71.5, 50]
}, {
name: 'Shawmut Hills',
data: [83.6, 78.8, 67]
}, {
name: 'Baxter',
data: [48.9, 38.8, 100]
}, {
name: 'Midtown',
data: [42.4, 33.2, 80]
}, {
type: 'scatter',
data: [55,60,70],
marker: {
symbol: 'square',
lineColor: '#FFFFFF',
lineWidth: 1,
radius: 8
},
name: 'Average'
}]
});
});
I had the same problem :) highcharts still does not provide any solution for this problem, but it is flexibel enough so that you can sort anyway - just by javascript.
Put your data in a separate value:
var dataMain = [{name:"test1",data:5}, {name:"test1",data:1},{name:"test1",data:2}]
In series you can just add a function which sorts your data:
series: (function(){
for(var i = 0;i<dataMain.length;i++){
dataMain[i].data = dataMain[i].data.sort(function(a,b){
return a[0] - b[0] ;
})
return dataMain;
}
Hope I got everything wright.
Got it to work, I believe. Trick is to add each column in correct order as a new serie with same type (column), reuse colors and hide legend...
Very hackish, the JS code to sort like 8 categories independently will be ugly but the result looks fine.
Edit: Updated fiddle, I see the spacing between the categories grows with series, doesn't look supernice.
My jsfiddle is here
$(function () {
$('#container').highcharts({
chart: {
inverted: true
},
title: {
text: 'Series sorted in within categories'
},
xAxis: {
categories: ['January']
},
series: [{
type: 'column',
name: 'Stockholm',
data: [{x:0, y:95, color: Highcharts.getOptions().colors[0]}]
}, {
type: 'column',
name: 'Göteborg',
data: [{x:0, y:80, color: Highcharts.getOptions().colors[1]}]
}, {
type: 'column',
name: 'Göteborg',
data: [{x: 1, name: 'February', y: 98, color: Highcharts.getOptions().colors[1] // VGR's color
}],
showInLegend: false,
dataLabels: {
enabled: false
}
}, {
type: 'column',
name: 'Stockholm',
data: [{x: 1, name: 'February', y: 80, color: Highcharts.getOptions().colors[0] // VGR's color
}],
showInLegend: false,
dataLabels: {
enabled: false
}
}]
});
});
br,
Jens
I think this can be done,
this may look like a little work around.
since we have a limited number of columns i mean 4 in the given example.
if we have arrays with sorting done with respect to each series then we can handle them.
on button click we can update the chart with new set of data as well as category array.
May be there is no solution from the APi.
According to me this is a possible approach.
Thanks,