Replies: 1 comment
-
I have recently been using the following hack to create my own custom defmodule KinoLens.InputRef do
@moduledoc """
This module allows other components to build Kino.Input style components where
1) The value can be read
2) Dependencies are tracked in the same way as Kino.Input
A few hacks are necessary to make this work:
- We create a hidden input with 0 height to make Livebook aware of an input
- We the hidden input in sync
"""
defstruct [:id, :session_pid, :value]
def register(default \\ nil) do
hidden_input = Kino.Input.text("", default: default)
session_pid =
case :sys.get_state(Process.group_leader()) do
%{send_to: pid} when is_pid(pid) -> pid
_ -> nil
end
# This is a workaround to retrieve the value from the hidden input without re-rendering
# The process that initiates the re-render
# If we don't do this within another process, Livebook will track changes and re-render
# the Kino in the calling process whenever the input value changes
value =
Task.async(fn ->
case Kino.Bridge.get_input_value(hidden_input.id) do
{:ok, v} -> v
_ -> default
end
end)
|> Task.await()
# Render the custom UI together with the hidden input and
# return the hidden input handle for reading and API use
Kino.render(Kino.Layout.grid([hidden_input], columns: 1, max_height: 0))
%KinoLens.InputRef{
id: hidden_input.id,
session_pid: session_pid,
value: value
}
end
def read(%KinoLens.InputRef{id: id}) do
case Kino.Bridge.get_input_value(id) do
{:ok, ""} -> nil
{:ok, value} -> value
_ -> nil
end
end
def write(%KinoLens.InputRef{id: id, session_pid: session_pid} = ref, ctx, value) do
GenServer.cast(
session_pid,
{:set_input_value, self(), id, value}
)
Kino.JS.Live.Context.broadcast_event(ctx, "value", value)
%{ref | value: value}
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.
Uh oh!
There was an error while loading. Please reload this page.
-
We have a custom data table component and, we would like the currently selected row to behave similarly to how a
Kino.Input.select
would behave.This means if we are to deploy our notebook as an app via teams, it would make it easier to implement master-detail views. You click on a row in the table, then a form in the next cell is rendered.
It means being able to take advantage of the following properties built-in
Kino.Input
components have:(We could use frames, but that is more complex than being able to create a bunch of cells and have them chained to each other.)
I looked at the Kino library and it looks like rendering bottoms out at a data structure that is then handled within livebook itself.
And Livebook traverses these inputs
Livebook.Notebook.Cell.find_inputs_in_output
so it looks like this is currently not possible even with low level APIs.If I had
Kino.Input.hidden
I could work around this because then I would just need to keep aselected_row_id
property in sync with the hidden input.Or perhaps there's a way to expose an API so, for a particular component, I can register an input and read/write input values.
Thoughts?
Beta Was this translation helpful? Give feedback.
All reactions