Created
May 16, 2021 16:10
-
-
Save sb8244/28ef0c216677b4e76523af94bdd2c613 to your computer and use it in GitHub Desktop.
This allows chartkick to be embedded in LiveViews
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Chartkick do | |
@moduledoc """ | |
Adapted from https://github.com/buren/chartkick-ex/blob/master/lib/chartkick.ex to work with LiveView. | |
Works in conjunction with Phoenix LiveView hooks to render charts using Chartkick.js library. | |
""" | |
require EEx | |
gen_chart_fn = fn chart_type -> | |
def unquote( | |
chart_type | |
|> Macro.underscore() | |
|> String.to_atom() | |
)( | |
data_source, | |
options \\ [] | |
) do | |
chartkick_chart(unquote(chart_type), data_source, options) | |
end | |
end | |
Enum.map( | |
~w(LineChart PieChart BarChart AreaChart ColumnChart ComboChart GeoChart ScatterChart Timeline), | |
gen_chart_fn | |
) | |
def chartkick_chart(klass, data_source, options \\ []) do | |
id = Keyword.get_lazy(options, :id, &Ecto.UUID.generate/0) | |
height = Keyword.get(options, :height, "300px") | |
width = Keyword.get(options, :width, "100%") | |
only = Keyword.get(options, :only) | |
case only do | |
:html -> | |
chartkick_tag(id, height, width) | |
:script -> | |
chartkick_script(klass, id, data_source, options) | |
_ -> | |
""" | |
#{chartkick_tag(id, height, width)} | |
#{chartkick_script(klass, id, data_source, options)} | |
""" | |
end | |
end | |
EEx.function_from_string( | |
:def, | |
:chartkick_script, | |
~s[<div id="<%= id %>-loader" | |
data-klass="<%= klass %>" | |
data-id="<%= id %>" | |
data-source="<%= data_json(data_source) %>" | |
data-options="<%= options_json(options) %>" | |
phx-hook="Chartkick" | |
></div>], | |
~w(klass id data_source options)a | |
) | |
EEx.function_from_string( | |
:def, | |
:chartkick_tag, | |
~s[<div id="<%= id %>" style="width: <%= width %>; height: <%= height %>; text-align: center; color: #999; line-height: <%= height %>; font-size: 14px; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif;">Loading...</div>], | |
~w(id height width)a | |
) | |
defp options_json(opts) when is_list(opts) do | |
opts | |
|> Keyword.get(:chart_opts, []) | |
|> Enum.into(%{}) | |
|> json_serializer().encode!() | |
|> Plug.HTML.html_escape() | |
end | |
defp options_json(opts) when is_bitstring(opts) do | |
opts | |
end | |
defp data_json(data) do | |
data | |
|> json_serializer().encode!() | |
|> Plug.HTML.html_escape() | |
end | |
defp json_serializer do | |
Application.get_env(:chartkick, :json_serializer, Jason) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Chartkick from 'chartkick' | |
import 'chartkick/chart.js' | |
const ChartkickHook = { | |
mounted() { | |
const chartId = this.el.dataset.id | |
const dataSource = JSON.parse(this.el.dataset.source) | |
const options = JSON.parse(this.el.dataset.options) | |
const klass = this.el.dataset.klass | |
this.chart = new Chartkick[klass](chartId, dataSource, options) | |
}, | |
destroyed() { | |
if (this.chart) { | |
this.chart.destroy() | |
} | |
} | |
} | |
export const hooks = { | |
Chartkick: ChartkickHook | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# File excluded for brevity, just the template aspect | |
~L""" | |
<%= raw Chartkick.line_chart(@chart_data, chart_opts: [dataset: %{tension: 0.1}]) %> | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment