I am using a Nuxt application with vue-charts. I have a barchart that I trying to see if there is a way to callback the numbers next to the chart. Some what like this
My barchart options look like this now.
barLostDollarChartOptions: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false,
},
title: {
display: true,
text: 'Daily NP Opportunity Costs'
},
scales: {
yAxes: [{
//Sets the Max value after re-rendering chart
beforeFit: function (scale){
let maxValue = 0
if (scale.chart.config && scale.chart.config.data && scale.chart.config.data.datasets) {
scale.chart.config.data.datasets.forEach(dataset => {
if (dataset && dataset.data) {
dataset.data.forEach(value => {
if (value > maxValue) {
maxValue = value
}
})
}
})
}
// After, set max option !!!
scale.options.ticks.max = maxValue
},
// afterFit: function (scale){
// console.log('yAxes',scale)
// let arr = Object.values(scale.chart.config.data.datasets[0].data);
// let min = Math.min(...arr);
// let max = Math.max(...arr);
// maxValueArray.push(max)
// // console.log( `Min value: ${min}, max value: ${max}` );
//
// }
}
],
xAxes: [{
ticks:{
callback: function(value, index, values) {
if(parseInt(value) >= 1000){
// console.log(value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","))
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
},
},
}]
}
},
But I am trying to see if there is a way that I can call back the number and render it next to the bar? any ideas?
You can use the datalabels plugin for this:
Chart.plugins.register(ChartDataLabels);
var options = {
type: 'horizontalBar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'orange'
}]
},
options: {
plugins: {
datalabels: {
anchor: 'end',
align: 'end',
formatter: (val) => ('$' + val)
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/1.0.0/chartjs-plugin-datalabels.js"></script>
</body>
I'm trying that the percentages in a pie-chart refresh when clicking in a legend to hide data.
So far, I can display the chart with percentages, but they don't change if I hide one of the legends.
This is the chart: initial chart
This is how looks after the click: after click
We expect that instead 55.6%, it shows 100%.
This is my code so far:
<script>
import {Pie} from "vue-chartjs";
import ChartJsPluginDataLabels from 'chartjs-plugin-datalabels';
export default {
extends: Pie,
ChartJsPluginDataLabels,
props: {
data: Array,
bg: Array,
labels: Array
},
data() {
return {
}
},
computed: {
chartData() {
return this.data
},
bgData() {
return this.bg
},
total() {
return this.data.reduce((a, b) => a + (b || 0), 0)
}
},
methods: {
renderPieChart() {
this.renderChart({
labels: this.labels,
datasets: [
{
label: "Data One",
backgroundColor: this.bgData,
data: this.chartData,
hoverBackgroundColor: "#f78733"
}
]
}, {
responsive: true,
plugins: {
datalabels: {
formatter: (value) => {
let sum = this
.$refs.canvas.getContext('2d').dataset._meta[1].total; //use this.total to fix percentages
let percentage = (value * 100 / sum).toFixed(1) + "%";
return percentage;
},
color: '#fff'
}
}
})
console.log()
},
updateSelected(point, event) {
const item = event[0]
this.selected = {
index: item._index,
value: this
.chartData
.datasets[0]
.data[item._index]
}
}
},
watch: {
bg: function () {
this.renderPieChart();
},
data: function () {
this.renderPieChart();
}
},
}
</script>
In order to obtain the expected result, you should define plugins.datalabels.formatter as follows:
formatter: (value, context) => {
return (value * 100 / context.dataset._meta[0].total).toFixed(1) + "%";
}
new Chart(document.getElementById("myChart"), {
type: "pie",
data: {
labels: ['Savings', 'House'],
datasets: [{
label: "Data One",
backgroundColor: ['#4e9258', '#64e986'],
data: [9, 7],
hoverBackgroundColor: "#f78733"
}]
},
options: {
plugins: {
datalabels: {
formatter: (value, context) => {
return (value * 100 / context.dataset._meta[0].total).toFixed(1) + "%";
},
color: '#fff'
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<canvas id="myChart" height="100"></canvas>
I want each color of the bar is different depending on the data I have in the database. The problem is when I used the codes below it only change the first bar the rest is not. How can I change each bar? Can somebody help me with my problem? Here's my code below
dynamicColor : function() {
var r = Math.floor(Math.random() * 255);
var g = Math.floor(Math.random() * 255);
var b = Math.floor(Math.random() * 255);
return "rgba(" + r + "," + g + "," + b + ", 0.5)";
},
poolColors : function(a) {
var pool = [];
for(var i = 0; i < a; i++) {
pool.push(this.dynamicColor());
}
return pool;
},
retrieveDistributedPerDayByLine : function() {
var self = this;
axios.post(this.urlRoot + this.api + "retrieve_transaction_per_day.php")
.then(response => {
console.log(response);
vm.distributed_per_day = response.data
var ctxChart = self.$refs.myChart.getContext('2d');
var myChart = new Chart(ctxChart, {
type: 'bar',
data: {
labels: vm.distributed_per_day.map(item => item.Day),
datasets: [{
label: 'Total Amount',
data: vm.distributed_per_day.map(item => item.Amount),
backgroundColor: [
this.poolColors(vm.distributed_per_day.length)
],
borderColor: [
this.poolColors(vm.distributed_per_day.length)
],
borderWidth: 1
}]
},
reponsive: true,
options: {
title : {
display : true,
text : "Distrubuted Reports per Day",
fontFamily: "sans-serif",
fontSize: 18
},
legend: {
display: false
},
tooltips: {
enabled: true,
padding: 10
}
}
});
}).catch(e => {
console.log(e)
});
},
the this.poolColors method is returning an array so you are passing an array inside an array hence it is considered as one element ... it should be like this :
backgroundColor: this.poolColors(vm.distributed_per_day.length),
borderColor: this.poolColors(vm.distributed_per_day.length)
Here i am trying to check all checkbox for using custom checkbox we can see here filterTemplate section and selectAll or unselectAll these are Bold for getting my point
<script>
$(function () {
$.ajax({
type: "GET",
url: "/MerchandiseList/GetMerchant"
}).done(function (data) {
//$("#leftMenu").hide();
//reloadpage(data);
var MyDateField = function (config) {
jsGrid.Field.call(this, config);
};
MyDateField.prototype = new jsGrid.Field({
sorter: function (date1, date2) {
return new Date(date1) - new Date(date2);
},
itemTemplate: function (value) {
if (value == "")
return "";
else {
var date = new Date(value).toDateString()
//var date = new Date(value).toDateString("MM/dd/yyyy")
//return new Date(value).toDateString();
//return value;
var d = new Date(date),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
var df = [month, day, year].join('/');
//var df = [year, month, day].join('/');
date = df;
return date;
}
},
insertTemplate: function (value) {
return this._insertPicker = $("<input>").datepicker({ defaultDate: new Date() });
},
editTemplate: function (value) {
if (value == "")
return this._editPicker = $("<input>").datepicker({ defaultDate: new Date() });
else {
return this._editPicker = $("<input>").datepicker().datepicker("setDate", new Date(value));
}
},
insertValue: function () {
if (this._insertPicker.datepicker("getDate") != null)
return this._insertPicker.datepicker("getDate"); //.toISOString("MM/dd/yyyy")
//else
// return this._insertPicker.datepicker("getDate");
},
editValue: function () {
//debugger
if (this._editPicker.datepicker("getDate") != null)
//.toISOString("MM/dd/yyyy")
return this._editPicker.datepicker("getDate");
//return this._editPicker.datepicker("getDate").toISOString();
//else
// return this._editPicker.datepicker("getDate");
}
});
jsGrid.fields.myDateField = MyDateField;
$("#jsGrid").jsGrid({
height: "50%",
width: "100%",
filtering: true,
editing: true,
editButtonTooltip: "Edit",
inserting: true,
sorting: true,
paging: true,
autoload: true,
pageButtonCount: 5,
pageSize: 15,
overflow: scroll,
confirmDeleting: true,
deleteConfirm: "Do you really want to delete the merchandise?",
//refreshtext: "Refresh",
//onRefreshed: function (args) { },
selecting: true,
controller: db,
fields: [
{
**filterTemplate**: function (_, item) { // how to get all grid items here? This return only single item but empty in Filter row.
return $("<input>").attr("type", "checkbox")
.prop("checked", $.inArray(item, selectedItems) > -1)
.on("change", function () {
$(this).is(":checked") ? selectAll(item) : unselectAll(item);
});
},
itemTemplate: function (_, item) {
return $("<input>").attr("type", "checkbox")
.prop("checked", $.inArray(item, selectedItems) > -1)
.on("change", function () {
$(this).is(":checked") ? selectItem(item) : unselectItem(item);
});
},
align: "center",
width: 50,
sorting: false,
filtering: false
},
{ type: "control" },
{
name: "Source", type: "text", width: 120, title: "Vendor"
},
{
name: "Description", type: "text", width: 210,
validate: { message: "Description is required!", validator: function (value) { return value != ""; } }
},
{
name: "ModelNumber", type: "text", width: 120, title: "Model#/Item"
},
{ name: "SKU", type: "text", width: 90 },
{ name: "SKU2", type: "text", width: 90 },
{ name: "Comments", type: "text", width: 200 },
{ name: "strReceiveDate", type: "myDateField", width: 80, align: "center", title: "Received" },
{ name: "Location", type: "select", items: data.loc, valueField: "LocationID", textField: "Description", width: 100 },
{ name: "Barcode", width: 80 },
{ name: "BarcodePrinted", type: "checkbox", title: "Barcode Printed", sorting: false },
//{ name: "strLastUpdatedDate", type: "myDateField", width: 80, title: "Last Updated" },
{ name: "strLastUsedDate", type: "myDateField", width: 80, title: "Last Updated" },
{ name: "DamageCode", type: "select", items: data.dam, valueField: "CodeID", textField: "CodeValue", title: "Damage" },
{ name: "strCreatedDate", editable: false, width: 80, title: "Created Date", type: "myDateField" },
{ name: "strShipDate", type: "myDateField", myCustomProperty: "bar", width: 80, title: "Ship Date" },
{ name: "strConsumeDate", type: "myDateField", myCustomProperty: "bar", width: 80, title: "Consume Date" },
{ name: "PendingShipment", type: "checkbox", title: "Pending", sorting: false, width: 60 },
{ name: "Donated", type: "checkbox", title: "Is Donated", sorting: false, width: 60 },
{ name: "ReturnRequested", type: "checkbox", title: "Return Requested", sorting: false },
{ name: "ReturnTo", type: "text", width: 150, title: "Return To" },
{ name: "Quantity", type: "number", width: 50, title: "Qty" },
{ name: "GroupName", type: "text", width: 150, title: "Group Name" },
{ name: "CustomerID", width: 100, title: "Customer ID" }
],
});
var selectedItems = [];
var selectItem = function (item) {
document.getElementById("hdn").value = document.getElementById("hdn").value + "," + item.Barcode;
selectedItems.push(item);
//debugger
var $grid = $("#jsGrid");
$grid.jsGrid("option", "editing", false);
$grid.jsGrid("option", "editing", true);
};
var unselectItem = function (item) {
selectedItems = $.grep(selectedItems, function (i) {
//debugger
return i !== item;
});
var value = document.getElementById("hdn").value;
value = value.replace(item.Barcode, "");
document.getElementById("hdn").value = value;
var $grid = $("#jsGrid");
$grid.jsGrid("option", "editing", false);
$grid.jsGrid("option", "editing", true);
};
var **selectAll** = function (item) {
document.getElementById("hdn").value = document.getElementById("hdn").value + "," + item.Barcode;
selectedItems.push(item);
var $grid = $("#jsGrid");
$grid.jsGrid("option", "editing", false);
$grid.jsGrid("option", "editing", true);
};
var **unselectAll** = function (item) {
selectedItems = $.grep(selectedItems, function (i) {
//debugger
return i !== item;
});
var value = document.getElementById("hdn").value;
value = value.replace(item.Barcode, "");
document.getElementById("hdn").value = value;
var $grid = $("#jsGrid");
$grid.jsGrid("option", "editing", false);
$grid.jsGrid("option", "editing", true);
};
});
});
here the output image here [https://i.stack.imgur.com/gMfwn.png][1]
But noting happens can any one help me
The Code works But I wanna Change Chart Type Dynamically. I tried Change Chart Type in function WeightLine However It does not work. It changes SeriesDefault type , I see new chart type in alert but does not draw new chart type.
var mydata=[{"date":"2013-03-06","data":2916,"name":"weight"},{"date":"2013-03-05","data":3708,"name":"weight"}];
function getFilter(xMin, xMax) {
return [{
field: "date",
operator: "gt",
value: xMin
}, {
field: "date",
operator: "lt",
value: xMax
}];
}
$("#line_chart_weight").kendoChart({
title: {
text: "weight"
},
dataSource:{
data: mydata,
group: {
field: "name"
},
sort: {
field: "date",
dir: "asc"
},
schema: {
model: {
fields: {
date: {
type: "date"
}
}
}
}
},
seriesDefaults: {
type: "scatterLine"
},
series: [{
xField:"date",
yField: "data"
}],
yAxis: {
labels: {
format: "{0}"
},
title: {
text: "KG",
padding: {
left: 20
}}
}, xAxis: {
labels:
{
rotation: -90,
format:"dd-MM-yyyy"
},
title: {
text: "Date",
padding: {
top: 20
}},
type:"date",
name:"CategoryAxis"
},
tooltip: {
visible: true,
format:"dd-MM-yyyy",
color:"white"
},
transitions: false,
drag: onDragw,
zoom: onDragw
});
var weight=$("#line_chart_weight").data("kendoChart");
function onDragw(e) {
var ds = weight.dataSource;
var options = weight.options;
e.originalEvent.preventDefault();
var categoryRange = e.axisRanges.CategoryAxis;
if (categoryRange) {
var xMin = categoryRange.min;
var xMax = categoryRange.max;
options.categoryAxis.min = xMin;
options.categoryAxis.max = xMax;
ds.filter(getFilter(xMin, xMax));
weight.redraw();
}
}
function WeightLine(WeightTypeString){ weight.options.seriesDefaults.type=WeightTypeString;alert(weight.options.seriesDefaults.type); weight.redraw();}
it is a bit weird but i write something to solve this. both of them worked for me. You can modify them for your code.
1.
var chart = $("#chartId").data("kendoChart");
chart.setOptions({ seriesDefaults: {type : "radarColumn"} });
chart.dataSource.read();
chart.refresh();
2.
var chart = $("#chartId").data("kendoChart");
for(i = 0; i< chart.options.series.length;i++){
chart.options.series[i].type = "radarColumn";
}
chart.refresh();