Support nil fields in forms (#2931)

This commit is contained in:
José Valim 2025-02-12 13:12:03 +01:00 committed by GitHub
parent 00f2fdf1d1
commit e1277fa62a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 14 additions and 9 deletions

View file

@ -57,7 +57,7 @@ defmodule Livebook.Notebook.Cell do
end
def find_inputs_in_output({_idx, %{type: :control, attrs: %{type: :form, fields: fields}}}) do
Keyword.values(fields)
for {_field, input} <- fields, input != nil, do: input
end
def find_inputs_in_output({_idx, output}) when output.type in [:frame, :tabs, :grid] do

View file

@ -437,7 +437,7 @@ defprotocol Livebook.Runtime do
}
| %{
type: :form,
fields: list({field :: atom(), input_output()}),
fields: list({field :: atom(), input_output() | nil}),
submit: String.t() | nil,
# Currently we always use true, but we can support
# other tracking modes in the future

View file

@ -3311,8 +3311,9 @@ defmodule Livebook.Session do
:form ->
Map.update!(attrs, :fields, fn fields ->
Enum.map(fields, fn {field, attrs} ->
{field, normalize_runtime_output({:input, attrs})}
Enum.map(fields, fn
{field, nil} -> {field, nil}
{field, attrs} -> {field, normalize_runtime_output({:input, attrs})}
end)
end)

View file

@ -13,8 +13,9 @@ defmodule LivebookWeb.Output.ControlFormComponent do
socket = assign(socket, assigns)
data =
Map.new(assigns.control.attrs.fields, fn {field, input} ->
{field, assigns.input_views[input.id].value}
Map.new(assigns.control.attrs.fields, fn
{field, nil} -> {field, nil}
{field, input} -> {field, assigns.input_views[input.id].value}
end)
if prev_data != nil and data != prev_data do
@ -38,6 +39,7 @@ defmodule LivebookWeb.Output.ControlFormComponent do
<div class="flex flex-col space-y-3">
<.live_component
:for={{_field, input} <- @control.attrs.fields}
:if={input}
module={LivebookWeb.Output.InputComponent}
id={"#{@id}-#{input.id}"}
input={input}
@ -75,7 +77,7 @@ defmodule LivebookWeb.Output.ControlFormComponent do
defp reset_inputs(socket) do
values =
for {field, input} <- socket.assigns.control.attrs.fields,
field in socket.assigns.control.attrs.reset_on_submit,
input != nil and field in socket.assigns.control.attrs.reset_on_submit,
do: {input.id, input.attrs.default}
send(self(), {:set_input_values, values, true})

View file

@ -548,7 +548,8 @@ defmodule LivebookWeb.SessionLiveTest do
id: "input1",
destination: test,
attrs: %{type: :text, default: "initial", label: "Name", debounce: :blur}
}
},
value: nil
],
submit: "Send",
report_changes: %{},
@ -575,7 +576,8 @@ defmodule LivebookWeb.SessionLiveTest do
|> element(~s/[data-el-outputs-container] button/, "Send")
|> render_click()
assert_receive {:event, "control_ref1", %{data: %{name: "sherlock"}, type: :submit}}
assert_receive {:event, "control_ref1",
%{data: %{name: "sherlock", value: nil}, type: :submit}}
end
test "file input", %{conn: conn, session: session, test: test} do