Skip to content

Instantly share code, notes, and snippets.

@tywhang
Last active June 26, 2024 15:04
Show Gist options
  • Save tywhang/b4a67180da816eb0695f to your computer and use it in GitHub Desktop.
Save tywhang/b4a67180da816eb0695f to your computer and use it in GitHub Desktop.
Easily add Charts into Dashing with Chartjs (Line, Bar, Radar, Polar Area, Pie, Doughnut)

smashing-chartjs

An easy interface to use all of chartjs.org's charts.

Inspired by my own pain and suffering of trying to add a simple chart to smashing

Make awesome charts like these:

## Installation ##### 1. Import Chartjs library In `dashboards/layout.erb`, add this script tag:

<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>

before this script tag:

<script type="text/javascript" src="/assets/application.js"></script>

2. Install smashing-chartjs

Run in terminal in project directory

smashing install b4a67180da816eb0695f

Example

Let's create a simple line chart!

Usage

Line Chart

<div
  data-id="line-chart"
  data-view="Chartjs"
  data-type="line"
  data-labels="Week 1,Week 2,Week 3,Week 4,Week 5"
  data-colornames="blue,blue,blue,blue,blue"
  data-datasets="10,39,20,49,87"
  data-height="400"
  data-width="400"
></div>

Bar Charts

<div
  data-id="bar-chart"
  data-view="Chartjs"
  data-type="bar"
  data-labels="Day 1,Day 2,Day 3,Day 4,Day 5"
  data-colornames="yellow,yellow,yellow,yellow,yellow"
  data-datasets="210,339,220,494,109"
  data-height="400"
  data-width="400"
></div>

Radar Charts

<div
  data-id="radar-chart"
  data-view="Chartjs"
  data-type="radar"
  data-labels="Crossfit,Yoga,Weight Lifting,Running,Swimming,Watching TV"
  data-colornames="yellow,yellow,yellow,yellow,yellow,yellow"
  data-datasets="210,339,220,234,311,494"
  data-height="400"
  data-width="400"
></div>

Polar Area Charts

<div
  data-id="chart-polarArea"
  data-view="Chartjs"
  data-type="polarArea"
  data-labels="Week 1,Week 2,Week 3,Week 4,Week 5"
  data-colornames="blue,yellow,green,cyan,gray"
  data-datasets="10,39,20,49,87"
  data-height="400"
  data-width="400"
></div>

Pie Charts

@pieChart(elementId, dataSets)

<div
  data-id="chart-pie"
  data-view="Chartjs"
  data-type="pie"
  data-labels="Pumpkin,Apple,Pizza,Rhubarb"
  data-colornames="red,green,yellow,gray"
  data-datasets="13,32,40,20"
  data-height="400"
  data-width="400"
></div>

Doughnut Charts

@doughnutChart(elementId, dataSets)

<div
  data-id="doughnut-pie"
  data-view="Chartjs"
  data-type="doughnut"
  data-labels="Apple Fritter,Chocolate,Maple"
  data-colornames="green,blue,darkgray"
  data-datasets="20,13,12"
  data-height="400"
  data-width="400"
></div>

Colors

Currently available colors

blue | cyan | darkgray | gray | green | lightgray | magenta | red | yellow

class Dashing.Chartjs extends Dashing.Widget
constructor: ->
super
@id = @get("id")
@type = @get("type")
@labels = @get("labels") && @get("labels").split(",")
@datasets = @get("datasets") && @get("datasets").split(",")
@colorNames = @get("colornames") && @get("colornames").split(",")
ready: ->
switch @type
when 'pie', 'doughnut', 'polarArea'
@circularChart @id, type: @type, labels: @labels, colors: @colorNames, datasets: @datasets
when 'line', 'bar', 'radar'
@linearChart @id, type: @type, labels: @labels, colors: @colorNames, datasets: @datasets
else
return
circularChart: (id, { type, labels, colors, datasets, options={} }) ->
data = @merge labels: labels, datasets: [@merge data: datasets, @colors(colors)]
new Chart(document.getElementById(id), { type: type, data: data }, options)
linearChart: (id, { type, labels, colors, datasets, options={} }) ->
data = @merge labels: labels, datasets: [@merge(@colors(colors), data: datasets)]
new Chart(document.getElementById(id), { type: type, data: data }, options)
merge: (xs...) =>
if xs?.length > 0
@tap {}, (m) -> m[k] = v for k, v of x for x in xs
tap: (o, fn) -> fn(o); o
colorCode: ->
blue: "151, 187, 205"
cyan: "0, 255, 255"
darkgray: "77, 83, 96"
gray: "148, 159, 177"
green: "70, 191, 189"
lightgray: "220, 220, 220"
magenta: "255, 0, 255"
red: "247, 70, 74"
yellow: "253, 180, 92"
colors: (colorNames) ->
backgroundColor: colorNames.map (colorName) => @backgroundColor(colorName)
borderColor: colorNames.map (colorName) => @borderColor(colorName)
borderWidth: colorNames.map (colorName) -> 1
pointBackgroundColor: colorNames.map (colorName) => @pointBackgroundColor(colorName)
pointBorderColor: colorNames.map (colorName) => @pointBorderColor(colorName)
pointHoverBackgroundColor: colorNames.map (colorName) => @pointHoverBackgroundColor(colorName)
pointHoverBorderColor: colorNames.map (colorName) => @pointHoverBorderColor(colorName)
color: (colorName) ->
backgroundColor: @backgroundColor(colorName)
borderColor: @borderColor(colorName)
borderWidth: 1
pointBackgroundColor: @pointBackgroundColor(colorName)
pointBorderColor: @pointBorderColor(colorName)
pointHoverBackgroundColor: @pointHoverBackgroundColor()
pointHoverBorderColor: @pointBackgroundColor(colorName)
backgroundColor: (colorName) -> "rgba(#{ @colorCode()[colorName] }, 0.2)"
borderColor: (colorName) -> "rgba(#{ @colorCode()[colorName] }, 1)"
pointBackgroundColor: (colorName) -> "rgba(#{ @colorCode()[colorName] }, 1)"
pointBorderColor: (colorName) -> "rgba(#{ @colorCode()[colorName] }, 1)"
pointHoverBackgroundColor: -> "fff"
pointHoverBorderColor: (colorName) -> "rgba(#{ @colorCode()[colorName] }, 0.8)"
circleColor: (colorName) ->
backgroundColor: "rgba(#{ @colorCode()[colorName] }, 0.2)"
borderColor: "rgba(#{ @colorCode()[colorName] }, 1)"
borderWidth: 1
hoverBackgroundColor: "#fff"
hoverBorderColor: "rgba(#{ @colorCode()['blue'] },0.8)"
<canvas data-bind-id="id" data-bind-data-height="height | default 200" data-bind-data-width="width | default 200"></canvas>
SCHEDULER.every "2s" do |job|
send_event("chart", {
type: "bar",
header: "Calories Burned",
labels: ["Day 1", "Day 2", "Day 3", "Day 4", "Day 5"],
colorNames: ["yellow", "yellow", "yellow", "yellow", "yellow"],
datasets: [210, 339, 220, 494, 109]
})
end
@Brianm0440
Copy link

@tywhang: Can you attach your complete line chart files?

  • widget.coffee
  • widget.html
  • widget.scss
  • sample.erb
  • job file

Thanks

@poalcospe
Copy link

Is it possible to link chartjs data to display with an Excel file ? So Excel table could be displayed as a chart dynamically

@odedgol
Copy link

odedgol commented Apr 12, 2017

example full one ? is anyone own?

@yuribak
Copy link

yuribak commented Apr 2, 2018

@tywhang

Getting the following error:

      return new Chart(document.getElementById(id).getContext("2d")).Bar(data);
-----------------------------------------------------------------------------
Uncaught TypeError: Cannot read property 'getContext' of null
    at BarChart.Dashing.Chartjs.Chartjs.barChart (application.js:15145)
    at BarChart.Dashing.BarChart.BarChart.ready (application.js:15943)
    at BarChart.<anonymous> (application.js:14532)
    at application.js:2084
    at Array.forEach (<anonymous>)
    at Event.Batman.Event.Event.eachHandler (application.js:2028)
    at Event.Batman.Event.Event.fireWithContext (application.js:2083)
    at BarChart.fire (application.js:2224)
    at Renderer.<anonymous> (application.js:14448)
    at Renderer.handlerWrapper (application.js:2191)

document.getElementById(id) evaluates to null, and rightly so, the DOM doesn't contain the canvas element from example.html. Not sure why though, I followed instructions to the letter. Any ideas?

@tywhang
Copy link
Author

tywhang commented Jul 2, 2018

Hello everyone!

I made this little helper library and I had no idea how many people are trying to use this.
Most of these issues are probably happening because the code hasn't been updated for a while.
I am currently working on updating the library so it's compatible with Smashing.
Afterwards I will work on making this library more useful, configurable, and easier to implement.

In the meantime, any PRs are greatly welcome and appreciated!
https://github.com/tywhang/smashing-chartjs

@tywhang
Copy link
Author

tywhang commented Jul 9, 2018

@yuribak

In widgets/example/example.html, you should have added something like:
<canvas id="myChart" width="400" height="300"></canvas>

In your .erb file make sure you call the widget with something like:
<div data-view="Example"></div>

@tywhang
Copy link
Author

tywhang commented Jul 10, 2018

@eyalzek @RolphH Code has now been updated to use Chart.js 2.7.2 with the ability pass in options.

@tywhang
Copy link
Author

tywhang commented Jul 10, 2018

@PadawanBreslau
Copy link

PadawanBreslau commented Jul 16, 2018

And as some of you ask in comments above how to use it with jobs - you pass args just like in every other job:
send_event('dashboard_name', {labels: ['Some', 'Labels', 'Of', 'Your', 'Chosing'], datasets: [12, 23, 34, 21, 32, 12], colors: ['green, yellow, magenta'] })

@tywhang: Thanks for your work :)

@tywhang
Copy link
Author

tywhang commented Aug 20, 2018

Thanks @PadawanBreslau, I just updated the gist with a jobs example.

@caitfriedlander
Copy link

Hi! I'm a totally novice with both Smashing and Chart.js and I'm running into an issue where my charts will not resize properly when I'm resizing the dahsboard. I'm wondering if anyone has ever had a similar experience? (I'll write a much more thorough post tonight but I'm just wondering if anyone has been able to solve any sort of similar issue where charts just aren't resizing correctly.

@tywhang
Copy link
Author

tywhang commented Oct 26, 2018

@caitfriedlander Are you having issues with this library in particular? You can customize the height and width of your charts by passing in the proper attributes. If you're wondering about dynamic resizing, I'm not so sure if Smashing is intended to be used for constantly changing heights and widths.

Here's a repository of a full example you can look at: https://github.com/tywhang/smashing-chartjs-example
Live example: https://github.com/tywhang/smashing-chartjs-example

@cevapIT
Copy link

cevapIT commented Nov 7, 2018

First of all: thanks for the widget, it's great!

Is there any way to change the labels size and color or let the axes start by zero?
I tried this in the job file, but it didn't work:
send_event("myChart", { type: "bar", header: "Bar chart demo", labels: ["first bar'", "second bar'"], colorNames: ["green", "blue"], datasets: [display_firstValue, display_secondValue], options: { legend: { labels: { fontColor: "white", fontSize: 30 } }, scales: { yAxes: [{ ticks: { fontColor: "white", fontSize: 30, stepSize: 300, beginAtZero: true } }], xAxes: [{ ticks: { fontColor: "white", fontSize: 26, stepSize: 300, beginAtZero: true } }] } } })

@brieuclambert
Copy link

Hi! Thanks a lot for the amazing work ! It's really great and easy to use.

Although I'm facing an issue with passing options to the charts, and nothing that I've tried seems to have any effect on the chart. I tried passing the options in the job file as in the comment above, putting the options in multiple places in the chartjs.coffee file, but none seems to work. Do you have an example of working chart with custom options? It would be amazing.

Thanks in advance!

@tywhang
Copy link
Author

tywhang commented Apr 19, 2019

Hello @cevapIT and @brieuclambert.

I unfortunately haven't had as much time as I would like to put in this project.
I'm happily accepting any PRs! This project definitely could use the love.

Thanks for using it though!

@grubbychicken
Copy link

Thanks @tywhang for this, it's great.
Any chance you can help me pass options to the charts please? I'm looking to disable the legend on a doughnut chart with something like this:

options: { legend: { display: false }

I'm sure there is a simple way to do this as I see you have accounted for the options in the coffee script. I just can't seem to pass the options so they work. Thanks in advance.

@tywhang
Copy link
Author

tywhang commented Apr 16, 2020

@grubbychicken Getting those options passed correctly is definitely on my TO-DO list. I haven't worked on this project in a while. It could take some time for me to get to it.

You are welcome to make a Pull Request! :D

@strelexx
Copy link

@grubbychicken Getting those options passed correctly is definitely on my TO-DO list. I haven't worked on this project in a while. It could take some time for me to get to it.

You are welcome to make a Pull Request! :D

Hi @tywhang
Thanks for the solution.
Could you please explain what options now available to pass and how to do this. I tried everything from above. It didn't work

@curi0sity97
Copy link

Hi,
I am having trouble setting up a pie chart with an additional layer. Havent been able to correclty pass a second dataset. Does anyone have a quick example/tip of how to do it? Thx!

@pvaramballypivot
Copy link

@tywhang I am seeing this error when I run smashing install b4a67180da816eb0695f

.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/smashing-1.3.4/lib/dashing/downloader.rb:14:in `initialize': No such file or directory @ rb_sysopen - https://api.github.com/gists/b4a67180da816eb0695f (Errno::ENOENT)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment