I’ve been using Chartkick for years, but upgrading to Rails 7 made me take a look at how I’d been trapping Chartkick events and upgrade it to work with Stimulus.
This article is a short summary of my lengthy YouTube video where I run through doing this line by line.
Using the Chart as a Filter
I am talking about trapping the clicking on a chart and using it as a kind of filter for the associated data. This screenshot shows the demo app I create in the video.
Capturing Events the Old Way
You could always do this. Here is how I was doing it inside a plain script
tag in our Rails 6 app.
document.getElementById('purchasesChart').onclick = function (evt) {
var purchasesChart = Chartkick.charts['purchasesChart'].getChartObject();
const points = purchasesChart.getElementsAtEventForMode(evt, 'nearest', { intersect: true }, true);
if (points.length) {
const firstPoint = points[0];
label = purchasesChart.data.labels[firstPoint.index];
// do something to reload the data based on the label
}
}
You could then use ajax
to call out the Rails app and load in some HTML.
Capturing Events with Stimulus
But now there is a movement to get javascript
off the page and into Stimulus controllers. We can do that very simply (it turns out. I could not find any coherent example of doing this on the web, which is why I did the video and this article!)
Here are the steps:
- Wrap the page (or at least the chart and the table of data) in a
div
that links into a Stimulus controller - In the Stimulus controller’s
connect
method set up theonClick
of the chart to call a function - In that function call out to another method on the Stimulus controller that uses
fetch
to request the data from our Rails Controller and replace the contents of thetable
with the new data.
Wrap the area in a div for the controller
I ended up with something like this, which sets up the id
of the chart on the page and also the URL to call to pull the data
<div class='outside'
data-controller="purchase-chart"
data-purchase-chart-id-value="purchasesChart"
data-purchase-chart-url-value="<%=purchases_only_purchases_path%>">
<%# the chart goes in here %>
</div>
Put the method on the Charts ‘onClick’
Inside the Stimulus controller set up the onClick
to capture the event. Something like this:
var chart = Chartkick.charts[this.idValue]
const myClickFunction = function (event, native, active) {
if (native.length > 0) {
let xAxisIndex = native[0].index
let label = chart.getChartObject().data.labels[xAxisIndex]
console.log("clicked on x-axis column " + xAxisIndex + "; label: " + label)
theController.load()
}
}
let chartConfig = chart.getChartObject().config
chartConfig.options.onClick = myClickFunction
Load the data
Another Stimulus controller method will actually load in the data
load() {
fetch(this.urlValue + '/?' + new URLSearchParams({
purchased_at: this.dataFilterValue
}))
.then(response => response.text())
.then(html => this.purchasesTarget.innerHTML = html)
}
And that’s it!
The code here is a bit stubbed out. For the full tutorial watch the video or subscribe to my Substack, which has a more detailed description of the process.
Talk to me!
You can find me on Twitter where I share insights on Ruby on Rails, discuss my journey with Zonmaster, and explore various aspects of life. You can also check out my YouTube channel where I cover various topics related to web development, including Ruby on Rails.
And guess what? I’ve recently released my first guide, “Getting Started with Ruby on Rails: A Step-by-Step Guide for Beginners” on Gumroad! 📚🚀 It’s a ‘Fair Price’ ebook, so you can get it for free, but any payment is greatly appreciated as it helps support my work and future guides. Don’t miss out on this opportunity to level up your web development skills with Rails!
Drop me a note on Twitter or LinkedIn if you have any questions or need help with your Rails project. Happy coding! 😊🎉