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) frameOne 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]) endlazy_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