Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/live_select.ex
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,11 @@ defmodule LiveSelect do
doc:
~s(if `true`, the current list of selectable options and the content of the input text field are preserved upon selection)

attr :keep_label_on_select, :boolean,
default: Component.default_opts()[:keep_label_on_select],
doc:
~s(if `true`, when in single mode, the input text field is preserved to the active label upon selection.)

attr :value, :any, doc: "used to manually set a selection - overrides any values from the form.
Must be a single element in `:single` mode, or a list of elements in `:tags` mode."

Expand Down
20 changes: 17 additions & 3 deletions lib/live_select/component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ defmodule LiveSelect.Component do
clear_tag_button_class: nil,
clear_tag_button_extra_class: nil,
keep_options_on_select: false,
keep_label_on_select: false,
current_text: "",
user_defined_options: false,
container_class: nil,
Expand Down Expand Up @@ -218,12 +219,25 @@ defmodule LiveSelect.Component do

@impl true
def handle_event(event, _params, socket) when event in ~w(focus click) do
keep_label_on_select =
socket.assigns.keep_label_on_select &&
socket.assigns.mode == :single &&
socket.assigns.selection != []

display_text =
if keep_label_on_select do
List.first(socket.assigns.selection).label
else
socket.assigns.current_text
end

socket =
socket
|> assign(current_text: if(keep_label_on_select, do: "", else: socket.assigns.current_text))
|> client_select(%{
input_event: false,
parent_event: socket.assigns[:"phx-focus"],
current_text: socket.assigns.current_text
current_text: display_text
})
|> assign(hide_dropdown: false)

Expand Down Expand Up @@ -542,8 +556,8 @@ defmodule LiveSelect.Component do

defp clear(socket, params) do
socket
|> assign(selection: [])
|> client_select(params)
|> assign(selection: [], current_text: "")
|> client_select(Map.put(params, :current_text, ""))
end

defp clear_options(socket) do
Expand Down
8 changes: 7 additions & 1 deletion lib/support/live_select_web/live/showcase_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ defmodule LiveSelectWeb.ShowcaseLive do
default: Component.default_opts()[:keep_options_on_select]
)

field(:keep_label_on_select, :boolean,
default: Component.default_opts()[:keep_label_on_select]
)

field(:mode, Ecto.Enum,
values: [:single, :tags, :quick_tags],
default: Component.default_opts()[:mode]
Expand Down Expand Up @@ -106,6 +110,7 @@ defmodule LiveSelectWeb.ShowcaseLive do
:disabled,
:options_styled_as_checkboxes,
:keep_options_on_select,
:keep_label_on_select,
:max_selectable,
:user_defined_options,
:mode,
Expand Down Expand Up @@ -145,7 +150,8 @@ defmodule LiveSelectWeb.ShowcaseLive do
(remove_defaults && value == Keyword.get(default_opts, option)) ||
(settings.mode == :single && option == :max_selectable) ||
(settings.mode != :single && option == :allow_clear) ||
(settings.mode == :quick_tags && option == :keep_options_on_select)
(settings.mode == :quick_tags && option == :keep_options_on_select) ||
(settings.mode != :single && option == :keep_label_on_select)
end)
|> Keyword.new()
end
Expand Down
7 changes: 7 additions & 0 deletions lib/support/live_select_web/live/showcase_live.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@
disabled: to_string(@settings_form[:mode].value) == "quick_tags"
)}
</label>
<label class="label cursor-pointer">
<span class="label-text mr-1">Keep label on select:</span>
{checkbox(@settings_form, :keep_label_on_select,
class: "toggle",
disabled: to_string(@settings_form[:mode].value) != "single"
)}
</label>
<%= label class: "label cursor-pointer" do %>
<span class="label-text mr-1">Disabled:&nbsp;</span>
{checkbox(@settings_form, :disabled, class: "toggle")}
Expand Down
88 changes: 88 additions & 0 deletions test/live_select_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@
assert_option_active(
live,
1,
get_in(expected_class(), [@style || default_style(), :active_option]) || ""

Check warning on line 868 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.15, 26)

this check/guard will always yield the same result

Check warning on line 868 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.14.1, 25)

this check/guard will always yield the same result
)
end

Expand Down Expand Up @@ -899,7 +899,7 @@
assert_selected_option_class(
live,
2,
get_in(expected_class(), [@style || default_style(), :selected_option]) || []

Check warning on line 902 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.15, 26)

this check/guard will always yield the same result

Check warning on line 902 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.14.1, 25)

this check/guard will always yield the same result
)
end

Expand Down Expand Up @@ -935,7 +935,7 @@
assert_available_option_class(
live,
2,
get_in(expected_class(), [@style || default_style(), :available_option]) || []

Check warning on line 938 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.15, 26)

this check/guard will always yield the same result

Check warning on line 938 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.14.1, 25)

this check/guard will always yield the same result
)
end

Expand Down Expand Up @@ -971,7 +971,7 @@
assert_unavailable_option_class(
live,
2,
get_in(expected_class(), [@style || default_style(), :unavailable_option]) || []

Check warning on line 974 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.15, 26)

this check/guard will always yield the same result

Check warning on line 974 in test/live_select_test.exs

View workflow job for this annotation

GitHub Actions / build (1.14.1, 25)

this check/guard will always yield the same result
)
end

Expand Down Expand Up @@ -1213,4 +1213,92 @@

refute_selected(live)
end

describe "when keep_label_on_select = true" do
setup %{conn: conn} do
stub_options(A: 1, B: 2, C: 3)

{:ok, live, _html} = live(conn, "/?keep_label_on_select=true")

type(live, "ABC")
select_nth_option(live, 2)
assert_selected(live, :B, 2)

%{live: live}
end

test "on focus, the text input displays the selected label", %{live: live} do
element(live, selectors()[:text_input])
|> render_focus()

assert_set_text_field(live, :B)
end

test "on click, the text input displays the selected label", %{live: live} do
element(live, selectors()[:text_input])
|> render_click()

assert_set_text_field(live, :B)
end

test "on blur, the text input is restored to the selected label", %{live: live} do
element(live, selectors()[:text_input])
|> render_focus()

element(live, selectors()[:text_input])
|> render_blur()

assert_set_text_field(live, :B)
end

test "blur then focus cycle preserves the selected label", %{live: live} do
element(live, selectors()[:text_input])
|> render_blur()

assert_set_text_field(live, :B)

element(live, selectors()[:text_input])
|> render_focus()

assert_set_text_field(live, :B)

element(live, selectors()[:text_input])
|> render_blur()

assert_selected_static(live, :B, 2)
end

test "without a selection, focus behaves as default", %{conn: conn} do
stub_options(A: 1, B: 2, C: 3)

{:ok, live, _html} = live(conn, "/?keep_label_on_select=true")

type(live, "ABC")

element(live, selectors()[:text_input])
|> render_focus()

assert_set_text_field(live, "ABC")
end

test "phx-focus parent_event fires normally on focus", %{conn: conn} do
stub_options(A: 1, B: 2, C: 3)

{:ok, live, _html} =
live(conn, "/?keep_label_on_select=true&phx-focus=focus-event-for-parent")

type(live, "ABC")
select_nth_option(live, 2)
assert_selected(live, :B, 2)

element(live, selectors()[:text_input])
|> render_focus()

assert_push_event(live, "select", %{
id: "my_form_city_search_live_select_component",
current_text: :B,
parent_event: "focus-event-for-parent"
})
end
end
end
Loading