import { Directive, ElementRef, Input, OnInit, Renderer2 } from '@angular/core';
import { UtilsService } from '../services/utils.service';
import Plotly from 'plotly.js-dist-min';
@Directive({
selector: '[appDynamicPlotly]'
})
export class DynamicPlotlyDirective implements OnInit {
@Input() public data: any;
@Input() public group: string = 'Month';
protected plot: any;
private currentType: string = 'bar'; // Default plot type
private currentMode: string = ''; // Default plot type
constructor(private elementRef: ElementRef, private utilsService: UtilsService, private renderer: Renderer2) {}
ngOnInit() {
this.plot = this.elementRef.nativeElement;
this.renderPlot();
}
private renderPlot() {
const trace: any = this.getTrace();
const layout: Partial<Plotly.Layout> = this.getLayout();
const config: Partial<Plotly.Config> = {
responsive: true,
displayModeBar: false,
displaylogo: false
};
Plotly.react(this.plot, trace, layout, config);
}
private getTrace() {
switch (this.currentType) {
case 'pie':
return [
{
labels: this.data[this.group], // Grouped data as labels
values: this.data.storage_state_kg, // Corresponding values
type: 'pie',
// textinfo: 'label+percent',
textposition: 'outside',
automargin: true,
marker: { colors: ['#046CC4', '#F066AC', '#3C8454', '#64323A', '#182D44'] },
hovertemplate: '%{label}<br>H₂ Production: %{value}<extra></extra>'
}
];
case 'line':
return [
{
x: this.data[this.group],
y: this.data.storage_state_kg,
type: 'scatter',
mode: 'lines',
name: 'H₂',
line: { color: '#046CC4', width: 2 },
hovertemplate: '%{x}<br>H₂ Production: %{y}<extra></extra>'
}
];
case 'scatter':
return [
{
x: this.data[this.group],
y: this.data.storage_state_kg,
type: 'scatter',
mode: 'markers',
name: 'H₂',
marker: { color: '#046CC4', size: 8 },
hovertemplate: '%{x}<br>H₂ Production: %{y}<extra></extra>'
}
];
case 'waterfall':
return [
{
x: this.data[this.group],
y: this.data.storage_state_kg,
type: 'waterfall',
name: 'H₂',
measure: Array(this.data.storage_state_kg.length).fill('relative'),
connector: { line: { color: '#7F7F7F' } },
hovertemplate: '%{x}<br>H₂ Production: %{y}<extra></extra>',
increasing: { marker: { color: '#046CC4' } },
decreasing: { marker: { color: '#E74C3C' } },
totals: { marker: { color: '#2ECC71' } }
}
];
case 'bar':
default:
return [
{
x: this.data[this.group],
y: this.data.storage_state_kg,
type: 'bar',
name: 'H₂',
marker: { color: '#046CC4' },
hovertemplate: '%{x}<br>H₂ Production: %{customdata}<extra></extra>',
customdata: this.data.storage_state_kg.map((val: number) =>
Number.isInteger(val) ? val.toFixed(0) : val.toFixed(3)
)
}
];
}
}
private getLayout(): Partial<Plotly.Layout> {
if (this.currentType === 'pie') {
return {
title: {
text: 'Dynamic Plot',
font: { size: 14 },
x: 0.5,
xanchor: 'center'
},
showlegend: true,
margin: { t: 50, b: 50, l: 60, r: 70 },
plot_bgcolor: '#F8F8F8',
paper_bgcolor: '#F8F8F8'
};
} else {
return {
title: {
text: 'Dynamic Plot',
font: { size: 14 },
x: 0.5,
xanchor: 'center'
},
xaxis: {
tickmode: 'array',
tickvals: this.data[this.group],
ticktext: this.data[this.group].map((val: any) =>
this.utilsService.getDateTextForChart(val, this.group)
),
tickfont: { size: 14, color: '#000000' },
showgrid: true,
tickangle: 0
},
yaxis: {
title: {
text: 'H₂ Storage State (MT H₂)',
font: { size: 16, color: '#000000' },
standoff: 30
},
tickfont: { size: 14, color: '#000000' },
showgrid: false,
rangemode: 'tozero'
},
dragmode: undefined,
barmode: this.currentType === 'bar' ? 'stack' : undefined,
margin: { t: 50, b: 50, l: 60, r: 70 },
bargap: 0.7,
plot_bgcolor: '#F8F8F8',
paper_bgcolor: '#F8F8F8'
};
}
}
changePlotType(type: string, mode: string) {
this.currentType = type; // Update the plot type
this.currentMode = mode; // Update the plot type
this.renderPlot(); // Re-render the plot with the new type
}
}
I’m working on a project using Plotly and Angular, where I need to allow users to switch between different chart types dynamically (e.g., bar, pie, scatter, waterfall, etc.).
Here I’m manually providing a few options that supports array type for x&y. Instead of this, is there any external library, plugin, or built-in feature in Plotly that can suggest appropriate chart types based on the structure or type of the dataset? For example, if the data is categorical vs. numerical, the tool should recommend bar or pie charts.