It work! thanks man, you save my report Thanks @mthelm85 and @andre1sk
I just tried referencing a local .js file within a notebook and I got an error in my browser telling me I canāt include local resources.
Yeah I sadly also discovered thisā¦ Do you know why this is the case? Looking at the āsourcesā tab in Chrome dev tools, it looks like the Pluto server only serves the static content needed for the interface, not custom JS files in the notebook repo.
@fonsp do you know if it is possible to serve custom JS files (for custom visualizations and such)?
@mthelm85 Hi, I have another question, It is possible to use the function
data_table(JSON2.write(data))
more than once in Pluto, the first time I use this print the table perfectly, but the second time I call the function whit other data, it doesnāt show anything.
Thanks in advance.
, I never thought about that. Itās because of the static id
for the <div>
where the Vue app is rendered. Use this version instead:
using JSON2
using Random
using Tables
function data_table(table)
app_id = randstring('a':'z')
d = Dict(
"headers" => [Dict("text" => string(name), "value" => string(name)) for name in Tables.columnnames(table)],
"data" => [Dict(string(name) => row[name] for name in Tables.columnnames(table)) for row in Tables.rows(table)]
)
djson = JSON2.write(d)
return HTML("""
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="$app_id">
<v-app>
<v-data-table
:headers="headers"
:items="data"
></v-data-table>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#$app_id',
vuetify: new Vuetify(),
data () {
return $djson
}
})
</script>
<style>
.v-application--wrap {
min-height: 10vh;
}
.v-data-footer__select {
display: none;
}
</style>
""")
end
Note that you now need to load the Random package.
@mthelm85 Thanks man actually I change the function just a little, but your advice help me a lot. Now Iām trying to save this function in a Module so I can call it from any .jl or Pluto notebook essentially, just typing using MyModule o the name you want, if you have the time it would be really usefull to have this module ready to download from GitHub, this hack that you did help me a lot, I know that is gonna be useful for a lot of people out there.
function data_table(data,columns,ids)
return HTML("""
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="$ids">
<v-app>
<v-data-table
:headers="headers"
:items="Valores"
:items-per-page=$columns
></v-data-table>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#$ids',
vuetify: new Vuetify(),
data () {
return $data
}
})
</script>
<style>
.v-application--wrap {
min-height: 1vh;
}
.v-data-footer__select {
display: none;
}
</style>
""")
end
Thanks again
Iām trying to save this function in a Module so I can call it from any .jl or Pluto notebook essentially, just typing using MyModule o the name you want, if you have the time it would be really usefull to have this module ready to download from GitHub, this hack that you did help me a lot, I know that is gonna be useful for a lot of people out there.
As requested:
I wouldnāt want to pollute the Julia registry with something like this but you can Pkg.add("https://github.com/mthelm85/PlutoDataTable.jl")
and it should work fine when calling using PlutoDataTable
in your notebook (assuming you do the install in the same environment youāre running the notebook from).
I would encourage you to check out PkgTemplates.jl as it makes doing things like this very easy I was able to throw this together, push to GitHub and then test in about 10 minutes.
Just tried it out, amazing!
It would be great to have this functionality in the PlutoUI package.
Maybe @fonsp can chime in. Iām happy to submit a PR to Pluto or PlutoUI but I suspect this approach is too hacky to incorporate into either of those Theyāre developing Pluto with React.js so I think the end game here would be to have interactive tables as the default via some React solution (which will undoubtedly be a lot of work). This workaround makes use of Vue.js and Vuetify and brings in those assets via a CDN.
Normally I would say that while we wrote Pluto with react, you can use anything inside user code! But in that case you are right, we want the interactive viewer to be built in for tables specifically
Hiā
Iām really newā¦ to all. But Iām learning by doing. Until now I have been using python and Jupyter to process some csv, but I want to move to Julia and Pluto. So, my question.
Do you think that I can use this procedure but instead of do a csv to dict, make a csv to dataframe and the to json?
The way the function is currently written you wonāt need to do any of that. You can load your csv directly:
using CSV
using PlutoDataTable
data = CSV.File("path/to/your/file.csv")
data_table(data) # this should output the interactive table
Note that TableView.jl works well with Jupyter notebooks. So you donāt need PlutoDataTable to view data easily in a notebook.
great, because first I make some operations on two csv merging data, the i an create de final csv and send it directly to the function
sorry, why intermediate csv files? you can just work with everything in memory using DataFrames
Right now, I use DataFrame to marge an operate wit de data in those CSV. but finally I have to send to my colleagues (that don use python or Julia or notebooks) an csv processed. So, what I want is make engaging notebook with Pluto if I can, to make then come to the dark side. And finally stop using googl services.
Dear All,
I am new to julialang.org and I am enclosing a little module of mine based on ideas from this interesting discussion.
Special thanks to mthelm85 for his great job!
module TabularUtilities
using DataFrames
using DelimitedFiles
using CSV
using JSON2
export show_data_table
"""
This module generalizes a solution given to a particular CSV case.
Its purpose is to attain a more general solution to be applied to bidimensional tables
and is based on ideas from the `Julia Discourse Forum`:
> Interactive Data Table in Pluto
https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678
> A nice little hack for creating interactive data tables in my Pluto notebooks (mthelm85)
Obs.: There are some coding simplifications and optimizations left to future revision.
"""
"Delimited_file -> Dictionary"
function delimited2dict(delimited_path, dlmiter='|')
delimited_file = readdlm(delimited_path, dlmiter, header=true, skipblanks=true)
return Dict(
"headers" => [Dict("text" => str, "value" => str) for str in delimited_file[2]],
"states" => [Dict([(delimited_file[2][i], delimited_file[1][j, i]) for i in 1:length(delimited_file[2])]) for j in 1:size(delimited_file[1],1)])
end
"DataFrame -> Dictionary"
function delimited2dict(df::DataFrame)
delimited_file = (convert(Matrix, df), reshape(names(df),(1,length(names(df)))))
return Dict(
"headers" => [Dict("text" => str, "value" => str) for str in delimited_file[2]],
"states" => [Dict([(delimited_file[2][i], delimited_file[1][j, i]) for i in 1:length(delimited_file[2])]) for j in 1:size(delimited_file[1],1)])
end
"Matrix -> Dictionary"
function delimited2dict(mt::AbstractMatrix)
delimited_file = (mt, reshape([string(i) for i in 1:length(mt[1,:])],(1,length(mt[1,:]))))
return Dict(
"headers" => [Dict("text" => string("C", str), "value" => str) for str in delimited_file[2]],
"states" => [Dict([(delimited_file[2][i], delimited_file[1][j, i]) for i in 1:length(delimited_file[2])]) for j in 1:size(delimited_file[1],1)]
)
end
"table_dict -> html table"
function data_table_html(data, num_items)
return HTML("""
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-data-table
:headers="headers"
:items="states"
:items-per-page=$num_items
></v-data-table>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return $data
}
})
</script>
<style>
.v-application--wrap {
min-height: 10vh;
}
.v-data-footer__select {
display: none;
}
</style>
""")
end
"Include a html data table into a Pluto notebook: delmtd_path to a CSV file"
function show_data_table(delmtd_path::String, dlmiter='|', n_lines=10)
data_table_html(JSON2.write(delimited2dict(delmtd_path, dlmiter)), n_lines)
end
show_data_table(delmtd_path::String, n_lines) = show_data_table(delmtd_path, '|', n_lines)
function show_data_table(df::DataFrame, n_lines=10)
data_table_html(JSON2.write(delimited2dict(df)), n_lines)
end
function show_data_table(mt::AbstractMatrix, n_lines=10)
data_table_html(JSON2.write(delimited2dict(mt)), n_lines)
end
end # module
Works great
As of today, TableView.jl still does not work out of the box inside Pluto.
Does anyone know how to make it work?
The new API with_js_link
in Pluto should make it easy to develop a really good interactive table viewer with lazy loading/filtering for Pluto!