Wrapping Chart.js
What I Did
I created a wrapper class called WrapBarChart for Chart.js. It exposes a draw() method that takes x-axis labels and y-axis data as arguments and renders a bar chart.
Why Composition Instead of Inheritance
There are two approaches to wrapping a library: inheriting from the Chart class, or holding a Chart instance internally (composition). I chose composition.
With inheritance, all methods of the parent class (Chart.js) are exposed externally, bloating the interface. With composition, you control exactly what's public, keeping the interface clean and minimal.
Implementation
class WrapBarChart {
constructor(ctx) {
this.ctx = ctx;
this.chart = null;
}
draw(labels, data) {
this.chart = new Chart(this.ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Y Axis',
data: data,
backgroundColor: 'green'
}]
},
options: {
scales: {
y: { beginAtZero: true }
}
}
});
}
}
const canvas = document.getElementById('myWrapChart');
const ctx = canvas.getContext('2d');
const chart = new WrapBarChart(ctx);
chart.draw(['Jan', 'Feb', 'Mar', 'Apr'], [30, 20, 35, 8]);
Live Example
Summary
All that complexity above — the Chart.js configuration, dataset setup, scale options — gets hidden inside the wrapper. The caller only needs this one line:
chart.draw(['Jan', 'Feb', 'Mar', 'Apr'], [30, 20, 35, 8]);
That's the real power of wrapping. The interface is so clean that anyone can render a chart without knowing anything about Chart.js internals. Using composition keeps that interface minimal and intentional.