Skip to content

Commit 1543f1d

Browse files
authored
Add :section slot to simple_form. (#1487)
* Add `:section` slot to `simple_form`. * Remove isExpanded attribute and related tests * Unformat tests
1 parent 134d909 commit 1543f1d

File tree

2 files changed

+178
-15
lines changed

2 files changed

+178
-15
lines changed

priv/templates/lvn.swiftui.gen/core_components.ex

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,15 +400,31 @@ defmodule <%= inspect context.web_module %>.CoreComponents.<%= inspect context.m
400400
include: ~w(autocomplete name rel action enctype method novalidate target multipart),
401401
doc: "the arbitrary attributes to apply to the form tag"
402402

403-
slot :inner_block, required: true
403+
slot :inner_block, required: true, doc: "won't be rendered if section slots are passed in"
404404
slot :actions, doc: "the slot for form actions, such as a submit button"
405+
slot :section, required: false, doc: "slot for creating sections inside the form" do
406+
attr :is_expanded, :boolean, doc: "a boolean value that determines the section’s expansion state (expanded or collapsed)"
407+
attr :header, :string, doc: "text to use as a section's header"
408+
attr :footer, :string, doc: "text to use as a section's footer"
409+
end
405410

406411
def simple_form(assigns) do
407412
~LVN"""
408413
<.form :let={f} for={@for} as={@as} {@rest}>
409414
<Form>
410-
<%%= render_slot(@inner_block, f) %>
411-
<Section>
415+
<%%= if @section == [] do %>
416+
<%%= render_slot(@inner_block, f) %>
417+
<%% else %>
418+
<%%= for section <- @section do %>
419+
<Section>
420+
<Text :if={not is_nil(Map.get(section, :header))} template={:header} content={Map.get(section, :header)} />
421+
422+
<%%= render_slot(section) %>
423+
<Text :if={not is_nil(Map.get(section, :footer))} template={:footer} content={Map.get(section, :footer)} />
424+
</Section>
425+
<%% end %>
426+
<%% end %>
427+
<Section :if={@actions != []}>
412428
<%%= for action <- @actions do %>
413429
<%%= render_slot(action, f) %>
414430
<%% end %>

test/live_view_native/swiftui/core_components_test.exs

Lines changed: 159 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,18 @@ defmodule LiveViewNative.SwiftUI.CoreComponentsTest do
2323
|> parse_sorted!()
2424
end
2525

26+
def trim(str) when is_binary(str), do: String.trim(str)
27+
def trim(list) when is_list(list), do: Enum.map(list, &trim/1)
28+
def trim(tuple) when is_tuple(tuple), do: tuple |> Tuple.to_list() |> trim() |> List.to_tuple()
29+
2630
@doc """
2731
Parses LVN templates into Floki format with sorted attributes.
2832
"""
2933
def parse_sorted!(value) do
3034
value
3135
|> parse_document!()
3236
|> Enum.map(&normalize_attribute_order/1)
37+
|> trim()
3338
end
3439

3540
defp normalize_attribute_order({node_type, attributes, content}),
@@ -315,7 +320,6 @@ defmodule LiveViewNative.SwiftUI.CoreComponentsTest do
315320
~X"""
316321
<LiveForm>
317322
<Form>
318-
<Section/>
319323
</Form>
320324
</LiveForm>
321325
"""
@@ -327,23 +331,166 @@ defmodule LiveViewNative.SwiftUI.CoreComponentsTest do
327331

328332
assigns = %{form: form}
329333

334+
template = ~LVN"""
335+
<.simple_form for={@form}>
336+
<.input field={@form[:email]} label="Email"/>
337+
</.simple_form>
338+
"""
339+
340+
assert t2h(template) ==
341+
~X"""
342+
<LiveForm>
343+
<Form>
344+
<VStack alignment="leading">
345+
<TextField id="user_email" name="user[email]" style="" text="[email protected]">Email</TextField>
346+
</VStack>
347+
</Form>
348+
</LiveForm>
349+
"""
350+
end
351+
352+
test "can render multiple sections in order" do
353+
params = %{
354+
"email" => "[email protected]",
355+
"first_name" => "Gloria",
356+
"last_name" => "Fuertes",
357+
"more_info" => "More info here"
358+
}
359+
360+
form = to_form(params, as: "user")
361+
362+
assigns = %{form: form}
363+
330364
template = ~LVN"""
331365
<.simple_form for={@form}>
332-
<.input field={@form[:email]} label="Email"/>
366+
<:section header="Name">
367+
<.input field={@form[:first_name]} label="First name"/>
368+
<.input field={@form[:last_name]} label="Last name"/>
369+
</:section>
370+
<:section footer="We will contact you here.">
371+
<.input field={@form[:email]} label="Email"/>
372+
</:section>
373+
<:section header="Extra info" footer="We will use this for..." is_expanded="false">
374+
<.input field={@form[:more_info]} label="More info"/>
375+
</:section>
333376
</.simple_form>
334377
"""
335378

336379
assert t2h(template) ==
337-
~X"""
338-
<LiveForm>
339-
<Form>
340-
<VStack alignment="leading">
341-
<TextField id="user_email" name="user[email]" style="" text="[email protected]">Email</TextField>
342-
</VStack>
343-
<Section/>
344-
</Form>
345-
</LiveForm>
346-
"""
380+
trim(~X"""
381+
<LiveForm>
382+
<Form>
383+
<Section>
384+
<Text template="header" content="Name" />
385+
<VStack alignment="leading">
386+
<TextField id="user_first_name" name="user[first_name]" style="" text="Gloria">First name</TextField>
387+
</VStack>
388+
<VStack alignment="leading">
389+
<TextField id="user_last_name" name="user[last_name]" style="" text="Fuertes">Last name</TextField>
390+
</VStack>
391+
</Section>
392+
<Section>
393+
<VStack alignment="leading">
394+
<TextField id="user_email" name="user[email]" style="" text="[email protected]">Email</TextField>
395+
</VStack>
396+
<Text template="footer" content="We will contact you here." />
397+
</Section>
398+
<Section>
399+
<Text template="header" content="Extra info" />
400+
<VStack alignment="leading">
401+
<TextField id="user_more_info" name="user[more_info]" style="" text="More info here">More info</TextField>
402+
</VStack>
403+
<Text template="footer" content="We will use this for..." />
404+
</Section>
405+
</Form>
406+
</LiveForm>
407+
""")
408+
end
409+
410+
test "can render section with footer" do
411+
params = %{"email" => "[email protected]"}
412+
form = to_form(params, as: "user")
413+
414+
assigns = %{form: form}
415+
416+
template = ~LVN"""
417+
<.simple_form for={@form}>
418+
<:section footer="A footer">
419+
<.input field={@form[:email]} label="Email"/>
420+
</:section>
421+
</.simple_form>
422+
"""
423+
424+
assert t2h(template) ==
425+
trim(~X"""
426+
<LiveForm>
427+
<Form>
428+
<Section>
429+
<VStack alignment="leading">
430+
<TextField id="user_email" name="user[email]" style="" text="[email protected]">Email</TextField>
431+
</VStack>
432+
<Text template="footer" content="A footer" />
433+
</Section>
434+
</Form>
435+
</LiveForm>
436+
""")
437+
end
438+
439+
test "can render section with header" do
440+
params = %{"email" => "[email protected]"}
441+
form = to_form(params, as: "user")
442+
443+
assigns = %{form: form}
444+
445+
template = ~LVN"""
446+
<.simple_form for={@form}>
447+
<:section header="A header">
448+
<.input field={@form[:email]} label="Email"/>
449+
</:section>
450+
</.simple_form>
451+
"""
452+
453+
assert t2h(template) ==
454+
trim(~X"""
455+
<LiveForm>
456+
<Form>
457+
<Section>
458+
<Text template="header" content="A header" />
459+
<VStack alignment="leading">
460+
<TextField id="user_email" name="user[email]" style="" text="[email protected]">Email</TextField>
461+
</VStack>
462+
</Section>
463+
</Form>
464+
</LiveForm>
465+
""")
466+
end
467+
468+
test "can render section" do
469+
params = %{"email" => "[email protected]"}
470+
form = to_form(params, as: "user")
471+
472+
assigns = %{form: form}
473+
474+
template = ~LVN"""
475+
<.simple_form for={@form}>
476+
<:section>
477+
<.input field={@form[:email]} label="Email"/>
478+
</:section>
479+
</.simple_form>
480+
"""
481+
482+
assert t2h(template) ==
483+
~X"""
484+
<LiveForm>
485+
<Form>
486+
<Section>
487+
<VStack alignment="leading">
488+
<TextField id="user_email" name="user[email]" style="" text="[email protected]">Email</TextField>
489+
</VStack>
490+
</Section>
491+
</Form>
492+
</LiveForm>
493+
"""
347494
end
348495
end
349496

0 commit comments

Comments
 (0)