Lazy rendered tabs #2860
petrkozorezov
started this conversation in
Ideas
Replies: 2 comments
-
Lazy rendering could be achieved with a button that triggers the computation and a frame for the result: frame = Kino.Frame.new(placeholder: false)
button = Kino.Control.button("Compute")
Kino.Frame.render(frame, button)
Kino.listen(button, fn _event ->
output = Kino.DataTable.new([%{id: 1, name: "Lazy"}])
Kino.Frame.render(frame, output)
end)
frame One could also implement something akin to lazy tabs, like this: lazy_tabs = fn tabs ->
frame = Kino.Frame.new(placeholder: false)
{names, funs} = Enum.unzip(tabs)
buttons = for name <- names, do: Kino.Control.button(to_string(name))
buttons
|> Enum.with_index(fn button, idx -> {:"#{idx}", button} end)
|> Kino.Control.tagged_stream()
|> Kino.listen(%{}, fn {tab, event}, cache ->
idx = tab |> Atom.to_string() |> String.to_integer()
cache = Map.put_new_lazy(cache, idx, fn -> Enum.fetch!(funs, idx).() end)
Kino.Frame.render(frame, cache[idx], to: event.origin)
{:cont, cache}
end)
Kino.Layout.grid([Kino.Layout.grid(buttons, columns: length(buttons)), frame])
end lazy_tabs.(
First: fn -> Kino.DataTable.new([%{id: 1, name: "First"}]) end,
Second: fn -> Kino.DataTable.new([%{id: 1, name: "Second"}]) end
) |
Beta Was this translation helpful? Give feedback.
0 replies
-
Another option is to keep using regular tabs, but doing the calculation and rendering async. Here's what it would look like: Here's the main code: frame = Kino.Frame.new()
async_render = fn frame, callback ->
Kino.Frame.render(frame, KinoSpinner.new())
Task.start(fn -> callback.(frame) end)
frame
end
expensive_computation = fn frame ->
Process.sleep(5_000)
Kino.Frame.render(frame, "expensiven result")
end
Kino.Layout.tabs([
{"Cheap computation", "hi"},
{"Expensive computation", async_render.(frame, expensive_computation)}
]) And the spinner component: defmodule KinoSpinner do
def new(dimensions \\ "30px") do
Kino.HTML.new("""
<div class="loader"></div>
<style>
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: #{dimensions};
height: #{dimensions};
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
""")
end
end |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I have a
Kino.Layout.tabs()
with a few heavy calculated tabs.And it's would be convenient to evaluate it lazily, only when corresponding tabs is opened.
Beta Was this translation helpful? Give feedback.
All reactions