Anko
April 7, 2024, 8:42am
1
I have started down the path of creating a Kino for rich data analysis on a DataFrame - something quite a bit richer than the Kino.DataTable.
The challenge is, the examples that i’m looking at use React for the interface. Coming from liveview this is quite the learning curve. Does anyone know if it’s possible to use liveview to create Kinos?
The custom Kinos require JavaScript for the client side, you can use any framework, but it’s not possible to use LiveView.
2 Likes
Anko
April 14, 2024, 2:11am
3
Maybe there is some upcoming work in this area!
opened 06:15PM - 26 Mar 24 UTC
It resembles LiveView. Here is a silly proof of concept:
```
import Kino.Con… trol
import Kino.Shorts
defmodule Kino.LiveFrame do
use GenServer, restart: :temporary
def start_link({frame, arg}) do
GenServer.start_link(__MODULE__, {frame, arg})
end
def init({frame, arg}) do
{:ok, state} = c_init(arg)
{:ok, {frame, state}, {:continue, :render}}
end
def handle_continue(:render, {frame, state}) do
{:noreply, render({frame, state})}
end
def handle_info({{__MODULE__, fun}, data}, {frame, state}) when is_function(fun, 2) do
state = fun.(data, state)
{:noreply, render({frame, state})}
end
defp render({frame, state}) do
Kino.Frame.render(frame, c_render(state))
{frame, state}
end
defp control(from, fun) do
Kino.Control.subscribe(from, {__MODULE__, fun})
from
end
## Callbacks (those can be callbacks in a new behaviour)
def c_init(:ok) do
{:ok, %{page: 0, name: nil, address: nil}}
end
defp step_zero(_, state) do
%{state | page: 1}
end
defp step_one(%{data: %{name: name}}, state) do
if name == "" do
%{state | name: name}
else
%{state | name: name, page: 2}
end
end
defp step_two(%{data: %{address: address}}, state) do
case address do
"BUMP" <> _ -> %{state | address: address <> "!"}
"" -> %{state | address: ""}
_ -> %{state | address: address, page: 3}
end
end
defp go_back(_, state) do
%{state | page: state.page - 1}
end
def c_render(%{page: 0}) do
button("Start")
|> control(&step_zero/2)
end
def c_render(%{page: 1} = state) do
form(
[name: Kino.Input.text("Name", default: state.name)],
submit: "Step one"
)
|> control(&step_one/2)
end
def c_render(%{page: 2} = state) do
Kino.Control.form(
[address: Kino.Input.text("Address", default: state.address)],
submit: "Step two"
)
|> control(&step_two/2)
|> add_go_back()
end
def c_render(%{page: 3} = state) do
"Well done, #{state.name}. You live in #{state.address}."
|> add_go_back()
end
defp add_go_back(element) do
button =
button("Go back")
|> control(&go_back/2)
grid([element, button])
end
end
frame = Kino.Frame.new() |> Kino.render()
Kino.start_child!({Kino.LiveFrame, {frame, :ok}})
```
We need `Kino.monitor_origins` before implementing it.
In case you’re going the route of making this a SmartCell, I made a template for them: GitHub - acalejos/kino_smartcell_template: A template project for creating Elixir Livebook Smart Cells with Tailwind and Vite
You could also use this for normal Kino.JS. Just remove the smart cell relevant code.
2 Likes
Anko
April 14, 2024, 9:19am
5
Really cool stuff!! thank you! As of yesterday vite was new to me, it’s been about 8 years since i did react or front end
But this does help
1 Like
Anko
May 11, 2024, 8:53am
6
Just wanted to thank you, i’ve started using this today and it’s excellent! it would have taken me months to work it all out.
2 Likes
Glad it helped! Thanks for letting me know!