I have created an Ember JS component which uses Highcharts 6 library to create different types of charts based on data and configuration provided to the component. However, when I am trying to use "dashStyle" or "marker: { fillColor: "#FFFF00"}" for any series(to get dashed line) or data point(to get colored marker based on point data) respectively, am not getting the desired results. However, on pasting the same config on jsfiddle, am able to get the desired chart output. Any help would be sincerely appreciated. Pasting the component code below:
import Ember from 'ember';
export default Ember.Component.extend({
chartId: undefined,
chartData: undefined,
selectedChartType: undefined,
chart: undefined,
allowedChartTypes: undefined,
customSlider: false,
slider: false,
showChartTypeSelector: false,
chartTypes: [
{label: 'Bar chart', value: 'bar', stacked: false, id: 'bar1', group: 1},
{label: 'Stacked Bar chart', value: 'bar', stacked: true, id: 'bar2', group: 1},
{label: 'Bar Range chart', value: 'columnrange', stacked: false, inverted: true, id: 'bar3', group: 2},
{label: '3D Bar chart', value: 'bar', stacked: false, threeD: true, id: 'bar4', group: 1},
{label: 'Column chart', value: 'column', stacked: false, id: 'column1', group: 1},
{label: 'Stacked Column chart', value: 'column', stacked: true, id: 'column2', group: 1},
{label: 'Column Range chart', value: 'columnrange', stacked: false, id: 'column3', group: 2},
{label: '3D Column chart', value: 'column', stacked: false, threeD: true, id: 'column4', group: 1},
{label: 'Area chart', value: 'area', stacked: false, id: 'area1', group: 1},
{label: 'Stacked Area chart', value: 'area', stacked: true, id: 'area2', group: 1},
{label: 'Area Range chart', value: 'arearange', stacked: false, id: 'area3', group: 2},
{label: 'Line chart', value: 'line', stacked: false, id: 'line', group: 1},
{label: 'Spline chart', value: 'spline', stacked: false, id: 'spline', group: 1},
{label: 'Pie chart', value: 'pie', stacked: false, id: 'pie1', group: 3},
{label: '3D Pie chart', value: 'pie', stacked: false, threeD: true, id: 'pie2', group: 3},
{label: 'Donut chart', value: 'pie', stacked: false, donut: true, id: 'donut1', group: 3},
{label: '3D Donut chart', value: 'pie', stacked: false, threeD: true, donut: true, id: 'donut2', group: 3},
{label: 'Scatter plot', value: 'scatter', stacked: false, id: 'scatter', group: 4},
{label: 'Bubble chart', value: 'bubble', stacked: false, id: 'bubble', group: 4},
{label: 'Progress chart', value: 'solidgauge', stacked: false, id: 'progress', group: 5}
],
chartDataObserver: Ember.observer('chartData', function(){
this.setChartType();
if(this.selectedChartType !== undefined){
this.drawChart();
}
}),
init() {
this._super(...arguments);
if(this.chartId === undefined){
this.set('chartId', `chart_${this.generateUUID()}`);
}
this.setChartType();
if(this.chartData.customTheme !== false){
this.setChartsTheme();
}
else {
this.removeTheme();
}
},
didInsertElement() {
this._super(...arguments);
if(this.selectedChartType !== undefined){
this.drawChart();
}
},
generateUUID() {
var d = new Date().getTime();
var uuid = 'xxxxxxxxxxxxyy45'.replace(/[xy]/g, function(c) {
return Math.floor((d+Math.random()*16)%16).toString(16);
});
return uuid;
},
removeTheme() {
let stylesheet = document.getElementById('custom-chart-styles');
if (stylesheet) {
stylesheet.remove();
}
},
setChartsTheme(){
let colors = ['#234EA1', '#FCBC06', '#EC2027', '#70BE44', '#C1D331', '#C979CB', '#32CD9F', '#0099FF', '#87A1FF', '#9C7ACB'];
if(this.chartData.colors !== undefined && this.chartData.colors.length > 0){
colors = Ember.copy(this.chartData.colors);
}
this.addCustomColorStyles(colors);
Highcharts.setOptions({
colors: colors
});
},
addCustomColorStyles(colors) {
let stylesheet = document.getElementById('custom-chart-styles');
if (!stylesheet) {
stylesheet = Ember.$('<style id="custom-chart-styles">').appendTo('head')[0];
}
let html = '';
colors.forEach((c,i)=>{
html += `\n.highcharts-color-${i} { fill: ${c} !important; stroke: ${c} !important; } `;
});
stylesheet.innerHTML = html;
},
setChartType(){
if(this.chartData.type !== undefined){
this.chartTypes.every(t=>{
if(t.id === this.chartData.type){
this.set('selectedChartType', t);
return false;
}
return true;
});
if(this.selectedChartType !== undefined){
this.set('allowedChartTypes', this.chartTypes.filter(type=>{
return this.selectedChartType.group === type.group;
}));
}
if([1,2,4].indexOf(this.selectedChartType.group) > -1){
if(this.chartData.customSlider === null){
this.set('slider', false);
this.set('customSlider', false);
}
else {
if(this.chartData.customSlider !== undefined){
this.set('customSlider', this.chartData.customSlider);
}
this.set('slider', !this.customSlider);
}
}
if(this.chartData.showChartTypeSelector !== undefined){
this.set('showChartTypeSelector', this.chartData.showChartTypeSelector);
}
}
},
getAxisObject(axis) {
let self = this, axisObject = {
type: axis.type,
categories: axis.categories,
description: axis.description,
max: axis.max,
min: axis.min,
title: {
text: axis.title
},
stackLabels: {
enabled: false,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
},
opposite: axis.opposite
};
if(axis.type === 'datetime'){
axisObject.events = {
afterSetExtremes: function(){
self.sendAction('onRangeChanged', this);
}
};
}
return axisObject;
},
processSeriesInformation(){
let series = [];
this.chartData.series.forEach((s,i)=>{
if(typeof s === 'string'){
series.push({
name: s,
data: this.chartData.data[i],
yAxis: 0
});
}
else {
series.push({
name: s.name,
data: this.chartData.data[i],
yAxis: s.yAxis !== undefined ? s.yAxis : 0,
colorIndex: s.colorIndex,
dashStyle: s.dashStyle
});
}
});
if(this.chartData.customSeries !== undefined){
if(this.chartData.customSeries.constructor === Array){
series.push(...this.chartData.customSeries);
}
else {
series.push(this.chartData.customSeries);
}
}
if(this.selectedChartType.group !== 3){
series.forEach(s=>{
if(s.data.length > 0){
if(s.data[0].constructor === Array) {
s.data.sort((a,b)=>{
return a[0] > b[0] ? 1 : b[0] > a[0] ? -1 : 0;
});
}
else {
let sort = s.data[0].sort === 'x' ? 'x' : 'y';
s.data.sort((a,b)=>{
return a[sort] > b[sort] ? 1 : b[sort] > a[sort] ? -1 : 0;
});
}
}
});
if(series.length > 0 && series[0].data.length > 0 && series[0].data[0].constructor === Array){
series.sort((a,b)=>{
return a.data[0][0] > b.data[0][0] ? 1 : b.data[0][0] > a.data[0][0] ? -1 : 0;
});
}
}
return series;
},
drawChart() {
let self = this;
if(Ember.$(`#${this.chartId}`)){
let series = this.processSeriesInformation(), stackTotalFormat = '', tooltipFormat = {}, config, axes = {},
legend = {
enabled: true,
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
};
if(this.selectedChartType.stacked){
stackTotalFormat = '<br/>Total: {point.stackTotal}<br/>';
}
if(this.chartData.legend !== undefined){
if(this.chartData.legend === false){
legend = false;
}
else if(this.chartData.legend === 'left' || this.chartData.legend === 'right') {
legend = {
enabled: true,
layout: 'vertical',
align: this.chartData.legend,
verticalAlign: 'middle'
};
}
else {
legend = {
enabled: true,
layout: 'horizontal',
align: 'center',
verticalAlign: this.chartData.legend
};
}
}
if(this.chartData.tooltipFormat !== undefined){
tooltipFormat = this.chartData.tooltipFormat;
}
if(this.chartData.axes === undefined || this.chartData.axes.x === undefined || this.chartData.axes.y === undefined){
axes = {x: [{}], y: [{}]};
}
else {
axes.x = [];
axes.y = [];
if(this.chartData.axes.x.constructor === Array){
this.chartData.axes.x.forEach(x=>{
axes.x.push(this.getAxisObject(x));
});
}
else {
axes.x.push(this.getAxisObject(this.chartData.axes.x));
}
if(this.chartData.axes.y.constructor === Array){
this.chartData.axes.y.forEach(y=>{
axes.y.push(this.getAxisObject(y));
});
}
else {
axes.y.push(this.getAxisObject(this.chartData.axes.y));
}
}
config = {
chart: {
renderTo: this.chartId,
type: this.selectedChartType.value,
borderColor: '#EBBA95',
borderWidth: 2,
borderRadius: '10px',
backgroundColor: '#FFF',
zoomType: 'xy',
inverted: this.selectedChartType.inverted,
options3d: {
enabled: this.selectedChartType.threeD,
alpha: 40
},
height: this.chartData.height,
width: this.chartData.width
},
credits: {
enabled: false
},
title: {
text: this.chartData.title
},
exporting: false,
series: series,
subtitle: {
text: this.chartData.subtitle
},
legend: legend,
xAxis: axes.x,
yAxis: axes.y,
tooltip: {
borderRadius: 10,
delay: 500,
headerFormat: tooltipFormat.header !== undefined ? tooltipFormat.header : '<b>Category: {point.x}</b><br/>',
pointFormat: tooltipFormat.point !== undefined ? tooltipFormat.point : `Series {series.name}: {point.y}<br/>`,
formatter: tooltipFormat.formatter,
split: tooltipFormat.split,
shared: !tooltipFormat.shared
},
plotOptions: {
column: {
stacking: this.selectedChartType.stacked ? 'normal' : false,
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'gray'
}
},
columnrange: {
dataLabels: {
enabled: true,
style: {
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'gray'
}
}
},
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
},
showInLegend: true,
innerSize: this.selectedChartType.donut ? this.chartData.innerSize ? this.chartData.innerSize : 70 : 0,
depth: this.selectedChartType.threeD ? 30 : 0
},
solidgauge: {
dataLabels: {
enabled: false,
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
},
stickyTracking: false,
rounded: false
},
series: {
marker: {
enabled: this.chartData.markersEnabled
},
stacking: this.selectedChartType.stacked ? 'normal' : false,
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'gray'
},
point: {
events: {
click: function(e) {
self.sendAction('onChartClicked', this);
},
legendItemClick: function () {
return false;
}
}
},
turboThreshold: 10000,
cursor: 'pointer'
}
},
rangeSelector: {
enabled: this.chartData.rangeSelector ? this.chartData.rangeSelector : false
},
navigator: {
enabled: this.slider
},
scrollbar: {
enabled: this.slider
}
};
if(this.selectedChartType.value === 'solidgauge'){
config.pane = {
startAngle: 0,
endAngle: 360,
background: [{
outerRadius: '100%',
innerRadius: '63%',
backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0.3).get(),
borderWidth: 0
}]
};
config.tooltip.positioner = (labelWidth) => {
return {
x: 200 - labelWidth / 4,
y: 180
};
};
config.yAxis.max = 100;
config.yAxis.min = 0;
config.series.forEach(s=>{
s.data = s.data.map(d=>{
return {
color: Highcharts.Color(Highcharts.getOptions().colors[0]),
outerRadius: '112%',
innerRadius: '63%',
y: d
};
});
});
}
this.set('chart', Highcharts.stockChart(config));
if(this.customSlider && this.chartData.rangeConfig === undefined){
this.chart.axes.forEach(axis=>{
if(axis.isXAxis){
Ember.set(this.chartData, 'rangeConfig', { min: axis.min, max: axis.max, type: this.chartData.axes.x.type === 'datetime' ? 'datetime': 'numeric', start: [axis.min, axis.max] });
}
});
}
}
},
actions: {
selectChartType(event, type){
this.set('selectedChartType', type);
this.drawChart();
},
rangeChanged(newRangeValues){
Ember.set(this.chartData.axes.x, 'min', newRangeValues[0]);
Ember.set(this.chartData.axes.x, 'max', newRangeValues[1]);
this.drawChart();
this.sendAction('onRangeChanged', this.chartData.axes.x);
}
}
});