Reputation: 1619
I tried:
./bin/importmap pin chart.js
which added this to config/importmap.rb
pin "chart.js", to: "https://ga.jspm.io/npm:[email protected]/dist/chart.mjs"
In application.js I added:
import 'chart.js'
When I try to create a new Chart I get "Chart is not defined".
If I try
import Chart from 'chart.js'
I get "The requested module 'chart.js' does not provide an export named 'default'"
import Chart from 'chart.js/auto'
says "Failed to resolve module specifier 'chart.js/auto'"
Upvotes: 4
Views: 3764
Reputation: 11
The case with JSPM links works for me but i was able to make it work for Rails 7.1.3 from vendor/javascript folder. May be somebody needs it.
Run the following command to pin the chart.js library:
bin/importmap pin chart.js
In my case it was added like that:
Pinning "chart.js" to vendor/javascript/chart.js.js via download from https://ga.jspm.io/npm:[email protected]/dist/chart.js
Pinning "@kurkle/color" to vendor/javascript/@kurkle/color.js via download from https://ga.jspm.io/npm:@kurkle/[email protected]/dist/color.esm.js
This will automatically add the library to your config/importmap.rb and download the chart.js library and its dependency @kurkle/color to your vendor/javascript
directory:
pin "chart.js" # @4.4.3
pin "@kurkle/color", to: "@kurkle--color.js" # @0.3.2
The chart.js library imports a file from a relative path that needs to be present in your application. To handle this:
Create a _ directory inside the vendor folder:
mkdir -p vendor/_
Download the required file from the CDN and place it in the vendor/_
directory. The file URL can be found by following the import path in the chart.js library:
curl https://ga.jspm.io/npm:[email protected]/_/6La3kzg5.js -o vendor/_/6La3kzg5.js
Add a route to serve the JavaScript file from the vendor/_
directory in config/routes.rb
:
get "/_/:filename", to: "assets#serve_js", constraints: { filename: /.*\.js/ }
Create a controller to handle serving the JavaScript file. Create a file app/controllers/assets_controller.rb
with the following content:
# frozen_string_literal: true
class AssetsController < ApplicationController
skip_before_action :verify_authenticity_token, only: %i[serve_js]
def serve_js
file_name = params[:filename]
file_path = Rails.root.join("vendor", "_", file_name)
if File.exist?(file_path)
send_file(file_path, type: "application/javascript", disposition: "inline")
else
render plain: "File not found", status: :not_found
end
end
end
there was no need to import "chart.js" in "application.js"
Directly import chart.js in your Stimulus controller without needing to include it in application.js. For example, in app/javascript/controllers/dashboard_controller.js
:
import { Controller } from "@hotwired/stimulus"
import { Chart, registerables } from "chart.js"
Chart.register(...registerables);
export default class extends Controller {
connect() {}
}
There is no need to precompile assets or something.
just run bin/dev
Upvotes: 1
Reputation: 1
This is how I got it to work on a rails 7 app with importmaps.
const { Chart, registerables } = await import('chart.js');
Chart.register(...registerables);
Upvotes: 0
Reputation: 179
I had the same struggle this weekend and kept happening upon this article, so posting my solution here.
A couple things of note:
bin/importmap pin
. Credit to this article: Using chart.js with importmaps in rail 7.config/importmap.rb
- Note: Running bin/importmap pin chart.js
should pull in one dependency (@kurkle/color). Be sure to skip --download, or you're in for a world of pain.
# Pin npm packages by running ./bin/importmap
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "chart.js", to: "https://ga.jspm.io/npm:[email protected]/dist/chart.js"
pin "@kurkle/color", to: "https://ga.jspm.io/npm:@kurkle/[email protected]/dist/color.esm.js"
app/javascript/application.js
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
import "chart.js"
app/javascript/controllers/barchart_controller.js
import {Controller} from "@hotwired/stimulus"
import { Chart, registerables } from "chart.js";
Chart.register(...registerables);
export default class extends Controller {
static targets = ['myChart'];
canvasContext() {
return this.myChartTarget.getContext('2d');
}
connect() {
new Chart(this.canvasContext(), {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}
}
Content from the div in my model's app/views/widgets/show.html.erb
<div data-controller="barchart">
<canvas id="bar-chart" data-barchart-target="myChart" width="800" height="450"></canvas>
</div>
Don't forget to rebuild assets (bin/rails assets:precompile).
Upvotes: 11