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
Uh oh!
There was an error while loading. Please reload this page.
-
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