How to format tool tip as currency in piechart chartJS? - ruby-on-rails

I am using chartJS in my rails app and my chart code is added below. When hovering over sections I need to display as "Label name: $ 636"...Now when hovering it displays as "Label name: 636". The current chart with tooltip is
var ctx = document.getElementById('dollar-issue-area').getContext('2d');
var that = this;
this.chart = new Chart(ctx, {
type: 'pie',
data: {
labels: <%= raw dollar_per_type.collect { |k, v| k } %>,
datasets: [{
label: 'Number of tickets',
data: <%= raw dollar_per_type.collect { |k, v| v } %>,
backgroundColor: palette('tol-dv', <%= raw dollar_per_type.collect { |k, v| k }.length %>).map(function(hex) {return '#' + hex;})
}]
},
options: {
title:{
display: true,
text: 'Dollar per Sub Issue Type from <%= start_date %> to <%= end_date %>'
},
legend: {
display: true,
labels: {
display: false,
fontSize: 10
}
}
}
});

you can use a tooltips callback function.
here, the label callback is used to customize the tooltip content...
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return data['labels'][tooltipItem['index']] + ': $' + data['datasets'][0]['data'][tooltipItem['index']];
}
}
}
see following working snippet...
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['confirmed', 'pending'],
datasets: [{
data: [67, 33],
backgroundColor: [
'rgba(41, 121, 255, 1)',
'rgba(38, 198, 218, 1)'
],
}]
},
options: {
title: {
display: true,
text: 'Dollar per Sub Issue Type'
},
legend: {
display: true,
labels: {
display: false,
fontSize: 10
}
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return data['labels'][tooltipItem['index']] + ': $' + data['datasets'][0]['data'][tooltipItem['index']];
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>

Related

Rails 7 Highcharts ganttChart is not a function

Highcharts is working when not calling Gantt chart in other views. I've played around trying to get this Gantt chart to work. Looks like there is a conflict with import map only calling highcharts and highcharts.ganttChart is not found. I've tried added the src url through a script tag directly in the html view but still getting this error.
Error msg <
Uncaught (in promise) TypeError: Highcharts.ganttChart is not a function
>
Javascript controller
```
import {Controller} from "#hotwired/stimulus"
export default class extends Controller {
connect() {
let today = new Date(),
day = 1000 * 60 * 60 * 24;
today.setUTCHours(0);
today.setUTCMinutes(0);
today.setUTCSeconds(0);
today.setUTCMilliseconds(0);
today = today.getTime();
let dateFormat = Highcharts.dateFormat;
let series
let chart; // global
async function requestData() {
const response = await fetch('http://localhost:3000/api/v1/charts/index');
if (response.ok) {
const data = await response.json();
series = data.map(function (job, i) {
let data = job.deals.map(function (phase) {
return {
id: 'deal-' + i,
project: phase.project,
client: phase.client,
phase: phase.phase,
start: new Date(phase.from).getTime(),
end: new Date(phase.to).getTime(),
y: i
};
});
return {
name: job.name,
data: data,
current: job.deals[job.current]
};
});
setTimeout(requestData, 1000);
console.log(series);
chart = Highcharts.ganttChart('container', {
series: series,
title: {
text: 'Crew Schedule'
},
tooltip: {
pointFormat: '<span>Client {point.client}</span><br/>' +
'<span>Project: {point.project}</span><br/>' +
'<span>Phase: {point.phase}</span><br/>' +
'<span>From: {point.start:%e. %b}</span><br/><span>To: {point.end:%e. %b}</span>'
},
lang: {
accessibility: {
axis: {
xAxisDescriptionPlural: 'The chart has a two-part X axis showing time in both week numbers and days.',
yAxisDescriptionSingular: 'The chart has a tabular Y axis showing a data table row for each point.'
}
}
},
scrollbar: {
enabled: true
},
rangeSelector: {
enabled: true,
selected: 0
},
accessibility: {
keyboardNavigation: {
seriesNavigation: {
mode: 'serialize'
}
},
point: {
valueDescriptionFormat: 'Assigned to {point.project} from {point.x:%A, %B %e} to {point.x2:%A, %B %e}.'
},
series: {
descriptionFormatter: function (series) {
return series.name + ', job ' + (series.index + 1) + ' of ' + series.chart.series.length + '.';
}
}
},
xAxis: {
currentDateIndicator: true
},
navigator: {
enabled: true,
liveRedraw: true,
series: {
type: 'gantt',
pointPlacement: 0.5,
pointPadding: 0.25,
accessibility: {
enabled: false
}
},
yAxis: {
min: 0,
max: 3,
reversed: true,
categories: []
}
},
yAxis: {
type: 'category',
grid: {
columns: [{
title: {
text: 'Crew'
},
categories: series.map(function (s) {
return s.name;
})
}]
}
}
})
}
return chart;
}
window.addEventListener('load', (event) => {
requestData();
});
}
}

How to display grouped bar chart using chart.js?

I am currently building a grouped bar chart, with two different datasets using chart.js. The code in the component.js file is as follows:
createChart(){
var lbls = ['Selling', 'Cost', 'Gross'];
var curYearData = [2345, 1234, 1111];
var preYearData = [3456, 2345, 1111];
var ctx = document.getElementById(‘barChart') as HTMLCanvasElement;
var barChart = new Chart(ctx, {
type: 'bar',
data: {
labels: lbls,
datasets: [
{
label: ‘2020',
data: curYearData,
backgroundColor: 'blue',
},
{
label: ‘2019',
data: preYearData,
backgroundColor: 'red',
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
However, I see no data displayed and instead I get an empty screen. How to create a grouped bar chart in chart.js?
There are two problems in your code.
First you don't correctly retrieve the 2D-Context.
var ctx = document.getElementById('barChart').getContext('2d');
Further you have some strange apostrophes that need to be changed.
Please have a look at your amended code below.
var lbls = ['Selling', 'Cost', 'Gross'];
var curYearData = [2345, 1234, 1111];
var preYearData = [3456, 2345, 1111];
var ctx = document.getElementById('barChart').getContext('2d');
var barChart = new Chart(ctx, {
type: 'bar',
data: {
labels: lbls,
datasets: [{
label: '2020',
data: curYearData,
backgroundColor: 'blue',
},
{
label: '2019',
data: preYearData,
backgroundColor: 'red',
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="barChart"></canvas>

why x-axis showing alternate months rather every month?

Following is my highcharts config, can you help me to why my alternate months are coming, and if i want to show every month, how do i do it ? Also, to change width of the bar if showing every month.
Highcharts.chart("energy_chart", {
chart: {
type: "column",
spacingBottom: 15,
spacingTop: 10,
spacingLeft: 10,
spacingRight: 10,
backgroundColor: "#f2f2f2",
events: {
load: function() {
var fin = new Date();
var finDate = fin.getDate();
var finMonth = fin.getMonth();
var finYear = fin.getFullYear();
var ini = new Date();
ini.setFullYear(ini.getFullYear() - 1);
var iniDate = ini.getDate();
var iniMonth = ini.getMonth();
var iniYear = ini.getFullYear();
if (this.yAxis[0].dataMax == 0) {
this.yAxis[0].setExtremes(null, 1);
}
//this.yAxis.set
console.log(new Date(Date.UTC(iniYear, iniMonth, iniDate)))
console.log(new Date(Date.UTC(finYear, finMonth, finDate)))
this.xAxis[0].setExtremes(
Date.UTC(iniYear, iniMonth, iniDate),
Date.UTC(finYear, finMonth, finDate)
);
},
drilldown: function(e) {
console.log('drilldown')
var charts_this = this;
var inidrillDate = new Date(e.point.x);
setTimeout(function() {
inidrillDate.setDate(0);
inidrillDate.setMonth(inidrillDate.getMonth());
var DateinidrillDate = inidrillDate.getDate();
var MonthinidrillDate = inidrillDate.getMonth();
var YearinidrillDate = inidrillDate.getFullYear();
var findrillDate = inidrillDate;
findrillDate.setMonth(findrillDate.getMonth() + 1);
findrillDate.setDate(findrillDate.getDate() - 1);
var DatefindrillDate = findrillDate.getDate();
var MonthfindrillDate = findrillDate.getMonth();
var YearfindrillDate = findrillDate.getFullYear();
console.log(Date.UTC(
YearinidrillDate,
MonthinidrillDate,
DateinidrillDate
))
console.log(Date.UTC(
YearfindrillDate,
MonthfindrillDate,
DatefindrillDate
))
charts_this.xAxis[0].setExtremes(
Date.UTC(
YearinidrillDate,
MonthinidrillDate,
DateinidrillDate
),
Date.UTC(
YearfindrillDate,
MonthfindrillDate,
DatefindrillDate
)
);
if (charts_this.yAxis[0].dataMax === 0) {
charts_this.yAxis[0].setExtremes(null, 1);
}
}, 0);
}
}
},
title: {
text: '<p className="energy_gen">Energy Generated</p>'
},
exporting: { enabled: false },
xAxis: {
type: "datetime",
labels: {
step: 1
},
dateTimeLabelFormats: {
day: "%e"
}
},
yAxis: {
title: {
text: "kWh"
}
},
credits: {
enabled: false
},
plotOptions: {
series: {
cursor: "pointer",
dataLabels: {
enabled: true,
format: "{point.y}"
},
color: "#fcd562",
point:{
events:{
click:function(event){
}
}
}
}
}
},
tooltip: {
formatter: function() {
if (this.point.options.drilldown) {
return (
"Energy generated: <b> " +
this.y +
"</b> kWh " +
"<br>" +
Highcharts.dateFormat("%b %Y", new Date(this.x))
);
} else {
return (
"Energy generated: <b> " +
this.y +
"</b> kWh " +
"<br>" +
Highcharts.dateFormat("%e %b %Y", new Date(this.x))
);
}
}
},
series: [{'data':obj.data,'name':obj.name,"color":"#4848d3"}],
drilldown: {
series: obj.data
}
});
Also, attaching the screenshot of the rendered highchart with drilldown.
,
Now drilldown graph(same sort a issue)
EDIT:
It turnsout to be a zoom issue, i.e if i zoomout enough, then it shows all points. So, how to show every point without zooimg out .
Working fiddle:
http://jsfiddle.net/gkumar77/w9ngp63u/5/
Use tickInterval property and set it to one month:
xAxis: {
type: "datetime",
tickInterval: 30 * 24 * 3600 * 1000,
labels: {
step: 1
},
dateTimeLabelFormats: {
day: "%e"
}
}
Live demo: http://jsfiddle.net/BlackLabel/q5coany2/
API: https://api.highcharts.com/highcharts/xAxis.tickInterval

I need to develop icicle chart using HighCharts

HI can I tweak tree map and do it ?
I can pass all data hierarchy .
its already implemented in d3 .
Can i use/tweak Any properties of highcharts to render icicle ?
You could use heatmap - see this SO question: Creating ICICLE Chart using Highcharts Library
Other way would be to use treemap. Unfortunately there is no default layout algorithm that would enable icicle chart, so it would have to be created.
How to create custom layout algorithm: http://www.highcharts.com/docs/chart-and-series-types/treemap
For icicle it will be better if children passed to layout algorithm will be unsorted. Feature can be changed by wrapping setTreeValues function.
Example: http://jsfiddle.net/c6bo2asn/
$(function () {
//start wapper
(function (H) {
H.wrap(H.seriesTypes.treemap.prototype, 'setTreeValues', function (proceed) {
var tree = arguments[1];
//setTreeValues: function (tree) {
var series = this,
childrenTotal = 0,
sorted = [],
val,
point = series.points[tree.i];
// First give the children some values
H.each(tree.children, function (child) {
child = series.setTreeValues(child);
series.insertElementSorted(sorted, child, function (el, el2) {
return 0;//do not sort
});
if (!child.ignore) {
childrenTotal += child.val;
} else {
// #todo Add predicate to avoid looping already ignored children
series.eachChildren(child, function (node) {
H.extend(node, {
ignore: true,
isLeaf: false,
visible: false
});
});
}
});
// Set the values
val = H.pick(point && point.value, childrenTotal);
H.extend(tree, {
children: sorted,
childrenTotal: childrenTotal,
// Ignore this node if point is not visible
ignore: !(H.pick(point && point.visible, true) && (val > 0)),
isLeaf: tree.visible && !childrenTotal,
name: H.pick(point && point.name, ""),
val: val
});
return tree;
//},
});
}(Highcharts));
//end wapper
//start layoutAlgorithm logic
function myFunction(parent, children) {
var childrenAreas = [],
widthSoFar = 0,
w;
Highcharts.each(children, function (child,i) {
if (child.level == 1) { //even lines
childrenAreas.push({
x: parent.x,
y: parent.y + parent.height*(i/children.length),
width: parent.width,
height: parent.height/children.length
});
} else {
w = parent.width * child.val/parent.val;
childrenAreas.push({
x: parent.x + widthSoFar,
y: parent.y,
width: child.name === '_empty' ? 0 : w,
height: parent.height
});
widthSoFar += w;
}
});
return childrenAreas;
}
//end layoutAlgorithm logic
//assign new layoutAlgorithm logic
Highcharts.seriesTypes.treemap.prototype.icicle = myFunction;
//create chart
$('#container').highcharts({
series: [{
type: "treemap",
layoutAlgorithm: 'icicle',
dataLabels: {
formatter: function(){
//hide _empty
return this.key === '_empty' ? '' : this.key;
},
rotation: -90
},
borderWidth: 0,
levels: [{
level: 2,
borderWidth: 1
}],
/*
level 1 data points are lines
*/
data: [{
id: 'top',
color: "#EC2500"
}, {
name: 'a Anne',
parent: 'top',
value: 50
}, {
name: 'a Rick',
parent: 'top',
value: 30
}, {
name: 'a Peter',
parent: 'top',
value: 20
}, {
id: 'second'
}, {
name: 'b Anne',
parent: 'second',
value: 30,
color: "#ECE100"
}, {
name: '_empty',
parent: 'second',
value: 20
}, {
name: 'b Peter',
parent: 'second',
value: 30,
color: "#EC9800"
}, {
name: '_empty',
parent: 'second',
value: 20
}, {
id: 'third',
color: '#EC9800'
}, {
name: 'o Anne',
parent: 'third',
value: 20
}, {
name: 'o Rick',
parent: 'third',
value: 10
}, {
name: '_empty',
parent: 'third',
value: 70
}, {
id: 'last',
color: '#669866'
}, {
name: '_empty',
parent: 'last',
value: 20
}, {
name: 'z Anne',
parent: 'last',
value: 10
}, {
name: '_empty',
parent: 'last',
value: 70
}]
}],
title: {
text: 'Fruit consumption'
}
});
});

jqGrid parameters. Can't be passed

I call web-service to fill jqGrid and wants to pass parameters to it
I use the following code (client side):
jQuery('#EmployeeTable').jqGrid({
datatype: function () {
var params = new Object();
params.page = 10;
params.Filter = true;
params.DateStart = null;
params.DateEnd = null;
params.TagID = null;
params.CategoryID = 3;
params.StatusID = 1;
params.IsDescription = true;
$.ajax({
url: '/Admin/IdeasJSON',
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(params),
dataType: "json",
success: function (data, st) {
if (st == "success") {
var grid = $("#EmployeeTable")[0];
grid.addJSONData(data);
}
},
error: function () {
alert("Error with AJAX callback");
}
});
},
also, there is propotype of web-method (MVC):
public JsonResult IdeasJSON(int? page, bool? Filter, DateTime? DateStart, DateTime? DateEnd, int? TagID, int? CategoryID, int? StatusID, bool? IsDescription)
Why all these parameters are null?
[ADDED 04/11]
jQuery(document).ready(function () {
var StatusID = null, Filter = null, page = null, DateStart = null, DateEnd = null, TagID = null, CategoryID = null, IsDescription = null;
if (jQuery.url.param('StatusID') != null) {
StatusID = jQuery.url.param('StatusID');
}
if (jQuery.url.param('Filter') != null) {
Filter = jQuery.url.param('Filter');
}
if (jQuery.url.param('page') != null) {
page = jQuery.url.param('page');
}
if (jQuery.url.param('DateStart') != null) {
DateStart = jQuery.url.param('DateStart');
}
if (jQuery.url.param('DateEnd') != null) {
DateEnd = jQuery.url.param('DateEnd');
}
if (jQuery.url.param('TagID') != null) {
TagID = jQuery.url.param('TagID');
}
if (jQuery.url.param('CategoryID') != null) {
CategoryID = jQuery.url.param('CategoryID');
}
if (jQuery.url.param('IsDescription') != null) {
IsDescription = jQuery.url.param('IsDescription');
}
jQuery('#EmployeeTable').jqGrid({
url: '/Admin/IdeasJSON',
datatype: 'json',
postData: { page: page, Filter: Filter, DateStart: DateStart, DateEnd: DateEnd, TagID: TagID, StatusID: StatusID, CategoryID: CategoryID, IsDescription: IsDescription },
jsonReader: {
page: "page",
total: "total",
records: "records",
root: "rows",
repeatitems: false,
id: ""
},
colNames: ['Logged By', 'Logging Agency (ID)', 'Title', 'Status', 'Points', 'Categories', 'Created Date', 'Description', 'Jira ID#', 'Portal Name', '', '', '', '', '', '', ''],
colModel: [
{ name: 'LoggedBy', width: 100 },
{ name: 'LoggingAgencyID', width: 85 },
{ name: 'Title', width: 100 },
{ name: 'Status', width: 100 },
{ name: 'Points', width: 40, align: 'center' },
{ name: 'Categories', width: 100 },
{ name: 'CreatedDate', width: 80, formatter: ndateFormatter },
{ name: 'Description', width: 300 },
{ name: 'JiraID', width: 55 },
{ name: 'PortalName', width: 100 },
{ name: 'IdeaID', width: 25, formatter: ActionDescriptionFormatter },
{ name: 'IdeaID', width: 25, formatter: ActionEditFormatter },
{ name: 'IdeaID', width: 25, formatter: ActionDeleteFormatter },
{ name: 'IdeaGridCommentsAndSubideas', width: 25, formatter: ActionIdeaGridCommentsAndSubideas },
{ name: 'IdeaGridCountVotes', width: 25, formatter: ActionIdeaGridCountVotes },
{ name: 'IdeaGridCountVotes', width: 25, formatter: ActionIdeaGridLinkIdeas },
{ name: 'IdeaGridCountVotes', width: 25, formatter: ActionIdeaGridIdeaType },
],
pager: '#EmployeeTablePager',
width: 1000,
viewrecords: true,
caption: 'Idea List',
excel: true
}).jqGrid('navGrid', '#EmployeeTablePager', {
add: false,
edit: false,
del: false,
search: false,
refresh: false
}).jqGrid('navButtonAdd', '#EmployeeTablePager', {
caption: " Export to Excel ",
buttonicon: "ui-icon-bookmark",
onClickButton: ReturnExcel,
position: "last"
}).jqGrid('navButtonAdd', '#EmployeeTablePager', {
caption: " Export to CSV ",
buttonicon: "ui-icon-bookmark",
onClickButton: ReturnCSV,
position: "last"
});
});
You should not use datatype as the function to use the JSON data. Probably you used template of very old examples.
For example in the "UPDATED" part of the answer you could find full demo project which demonstrate how to use jqGrid in ASP.MVC 2.0 inclusive paging, sorting and filtering/advanced searching.
If you want post some additional parameters to the server as a part of jqGrid request you should use postData parameters in the form postData: {CategoryID: 3, StatusID: 1, IsDescription:true, Filter: true}

Resources