# Interactive Data Table in Pluto.jl (via a silly hack)

**URL:** <https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678>\
**Category:** Web Stack\
**Created:** [August 10, 2020, 12:39pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678 "2020-08-10T12:39:18Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![Peter24K2G](https://avatars.discourse-cdn.com/v4/letter/p/a9adbd/32.png) [@Peter24K2G](https://discourse.julialang.org/u/Peter24K2G)\
**Post date:** [October 15, 2020, 1:29am UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/21 "2020-10-15T01:29:09Z")

</div>

It work! thanks man, you save my report Thanks @mthelm85 and @andre1sk

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [October 15, 2020, 1:16pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/22 "2020-10-15T13:16:49Z")

</div>

> [@bhoov](#):
>
> This hack is genius and it gets me thinking – is there any way to build our own more complex javascript/Vue visualizations in a local file (say in the same repository as our notebook) and import them into pluto?

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.

---

<div class="post-metadata">

**Author:** ![bhoov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bhoov/32/18604_2.png) [@bhoov](https://discourse.julialang.org/u/bhoov)\
**Post date:** [October 15, 2020, 1:25pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/23 "2020-10-15T13:25:31Z")

</div>

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)?

---

<div class="post-metadata">

**Author:** ![Peter24K2G](https://avatars.discourse-cdn.com/v4/letter/p/a9adbd/32.png) [@Peter24K2G](https://discourse.julialang.org/u/Peter24K2G)\
**Post date:** [October 16, 2020, 4:50pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/24 "2020-10-16T16:50:11Z")

</div>

@mthelm85 Hi, I have another question, It is possible to use the function

```nohighlight
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.

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [October 16, 2020, 5:06pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/25 "2020-10-16T17:06:28Z")

</div>

> [@Peter24K2G](#):
>
> @mthelm85 Hi, I have another question, It is possible to use the function
> 
> ```julia
> 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.

😆, 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:

```julia
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.

---

<div class="post-metadata">

**Author:** ![Peter24K2G](https://avatars.discourse-cdn.com/v4/letter/p/a9adbd/32.png) [@Peter24K2G](https://discourse.julialang.org/u/Peter24K2G)\
**Post date:** [October 16, 2020, 6:44pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/26 "2020-10-16T18:44:00Z")

</div>

@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.

```nohighlight
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

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [October 18, 2020, 5:17pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/27 "2020-10-18T17:17:59Z")

</div>

> 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:

> **[GitHub - mthelm85/PlutoDataTable.jl: An interactive data table for Pluto.jl...](https://github.com/mthelm85/PlutoDataTable.jl)**
>
> An interactive data table for Pluto.jl notebooks. Contribute to mthelm85/PlutoDataTable.jl development by creating an account on GitHub.

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](https://github.com/invenia/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.

---

<div class="post-metadata">

**Author:** ![lungben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lungben/32/12314_2.png) [@lungben](https://discourse.julialang.org/u/lungben)\
**Post date:** [October 18, 2020, 6:59pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/28 "2020-10-18T18:59:19Z")

</div>

Just tried it out, amazing!

It would be great to have this functionality in the PlutoUI package.

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [October 18, 2020, 7:09pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/29 "2020-10-18T19:09:55Z")

</div>

> [@lungben](#):
>
> 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.

---

<div class="post-metadata">

**Author:** ![fonsp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fonsp/32/222349_2.png) [@fonsp](https://discourse.julialang.org/u/fonsp)\
**Post date:** [October 22, 2020, 9:15am UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/30 "2020-10-22T09:15:48Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![alvarmaciel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alvarmaciel/32/18586_2.png) [@alvarmaciel](https://discourse.julialang.org/u/alvarmaciel)\
**Post date:** [October 22, 2020, 2:25pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/31 "2020-10-22T14:25:55Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![mthelm85](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mthelm85/32/224164_2.png) [@mthelm85](https://discourse.julialang.org/u/mthelm85)\
**Post date:** [October 22, 2020, 2:37pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/32 "2020-10-22T14:37:18Z")

</div>

> [@alvarmaciel](#):
>
> 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:

```julia
using CSV
using PlutoDataTable

data = CSV.File("path/to/your/file.csv")
data_table(data) # this should output the interactive table

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [October 22, 2020, 2:38pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/33 "2020-10-22T14:38:54Z")

</div>

Note that TableView.jl works well with Jupyter notebooks. So you don’t need PlutoDataTable to view data easily in a notebook.

---

<div class="post-metadata">

**Author:** ![alvarmaciel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alvarmaciel/32/18586_2.png) [@alvarmaciel](https://discourse.julialang.org/u/alvarmaciel)\
**Post date:** [October 22, 2020, 2:53pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/34 "2020-10-22T14:53:25Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [October 22, 2020, 2:55pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/35 "2020-10-22T14:55:57Z")

</div>

sorry, why intermediate csv files? you can just work with everything in memory using DataFrames

---

<div class="post-metadata">

**Author:** ![alvarmaciel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alvarmaciel/32/18586_2.png) [@alvarmaciel](https://discourse.julialang.org/u/alvarmaciel)\
**Post date:** [October 22, 2020, 3:03pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/36 "2020-10-22T15:03:15Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Orlando\_Soares](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/orlando_soares/32/19041_2.png) [@Orlando\_Soares](https://discourse.julialang.org/u/Orlando_Soares)\
**Post date:** [October 29, 2020, 10:41pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/37 "2020-10-29T22:41:43Z")

</div>

Dear All,

I am new to [julialang.org](http://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!

```julia
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

```

---

<div class="post-metadata">

**Author:** ![fieldofnodes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fieldofnodes/32/15858_2.png) [@fieldofnodes](https://discourse.julialang.org/u/fieldofnodes)\
**Post date:** [June 28, 2021, 2:12pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/38 "2021-06-28T14:12:55Z")

</div>

> [@mthelm85](#):
>
> `data_table`

Works great

---

<div class="post-metadata">

**Author:** ![schlichtanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schlichtanders/32/32145_2.png) [@schlichtanders](https://discourse.julialang.org/u/schlichtanders)\
**Post date:** [July 19, 2024, 12:54pm UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/39 "2024-07-19T12:54:34Z")

</div>

As of today, TableView.jl still does not work out of the box inside Pluto.

Does anyone know how to make it work?

---

<div class="post-metadata">

**Author:** ![fonsp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fonsp/32/222349_2.png) [@fonsp](https://discourse.julialang.org/u/fonsp)\
**Post date:** [October 24, 2024, 6:47am UTC](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678/40 "2024-10-24T06:47:57Z")

</div>

The new API [`with_js_link`](https://plutojl.org/en/docs/abstractplutodingetjes/#with_js_link) in Pluto should make it easy to develop a really good interactive table viewer with lazy loading/filtering for Pluto!

[Previous page](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678.md?page=1)

[Next page](https://discourse.julialang.org/t/interactive-data-table-in-pluto-jl-via-a-silly-hack/44678.md?page=3)
