From dff410955e41145848376784c03fe28ba1c4fd85 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Mon, 12 Feb 2024 15:52:54 -0800 Subject: [PATCH] Retain dropdown value if choices have been changed (#7401) * dropdown choice bug * add changeset * add changeset --------- Co-authored-by: gradio-pr-bot --- .changeset/tasty-spies-spend.md | 6 +++++ js/dropdown/dropdown.test.ts | 39 +++++++++++++++++++++++++++--- js/dropdown/shared/Dropdown.svelte | 19 ++++++++++++--- 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 .changeset/tasty-spies-spend.md diff --git a/.changeset/tasty-spies-spend.md b/.changeset/tasty-spies-spend.md new file mode 100644 index 0000000000..76894fbc20 --- /dev/null +++ b/.changeset/tasty-spies-spend.md @@ -0,0 +1,6 @@ +--- +"@gradio/dropdown": patch +"gradio": patch +--- + +fix:Retain dropdown value if choices have been changed diff --git a/js/dropdown/dropdown.test.ts b/js/dropdown/dropdown.test.ts index e9b53620c2..e27b7a4eab 100644 --- a/js/dropdown/dropdown.test.ts +++ b/js/dropdown/dropdown.test.ts @@ -124,8 +124,6 @@ describe("Dropdown", () => { const item: HTMLInputElement = getByLabelText( "Dropdown" ) as HTMLInputElement; - const change_event = listen("change"); - const select_event = listen("select"); item.focus(); await event.keyboard("other"); @@ -135,7 +133,7 @@ describe("Dropdown", () => { const { getByLabelText, listen } = await render(Dropdown, { show_label: true, loading_status, - value: "default", + value: "new ", label: "Dropdown", max_choices: undefined, allow_custom_value: true, @@ -156,7 +154,7 @@ describe("Dropdown", () => { await event.keyboard("kevin"); await item.blur(); - assert.equal(item.value, "kevin"); + assert.equal(item.value, "new kevin"); assert.equal(change_event.callCount, 1); }); @@ -407,4 +405,37 @@ describe("Dropdown", () => { await item.blur(); expect(item.value).toBe("apple"); }); + + test("updating choices should keep the dropdown focus-able and change the choice name", async () => { + const { getByLabelText, component } = await render(Dropdown, { + show_label: true, + loading_status, + value: "apple_internal_value", + allow_custom_value: false, + label: "Dropdown", + choices: [ + ["apple_choice", "apple_internal_value"], + ["zebra_choice", "zebra_internal_value"] + ], + filterable: true, + interactive: true + }); + + const item: HTMLInputElement = getByLabelText( + "Dropdown" + ) as HTMLInputElement; + + await expect(item.value).toBe("apple_choice"); + + component.$set({ + choices: [ + ["apple_new_choice", "apple_internal_value"], + ["zebra_new_choice", "zebra_internal_value"] + ] + }); + + await item.focus(); + await item.blur(); + await expect(item.value).toBe("apple_new_choice"); + }); }); diff --git a/js/dropdown/shared/Dropdown.svelte b/js/dropdown/shared/Dropdown.svelte index 19b009b11e..0a5d7861ec 100644 --- a/js/dropdown/shared/Dropdown.svelte +++ b/js/dropdown/shared/Dropdown.svelte @@ -8,8 +8,9 @@ export let label: string; export let info: string | undefined = undefined; - export let value: string | number | (string | number)[] | undefined = []; - let old_value: string | number | (string | number)[] | undefined = []; + export let value: string | number | (string | number)[] | undefined = + undefined; + let old_value: string | number | (string | number)[] | undefined = undefined; export let value_is_output = false; export let choices: [string, string | number][]; let old_choices: [string, string | number][]; @@ -92,9 +93,19 @@ } $: { - if (choices !== old_choices || input_text !== old_input_text) { - filtered_indices = handle_filter(choices, input_text); + if (choices !== old_choices) { + set_input_text(); old_choices = choices; + filtered_indices = handle_filter(choices, input_text); + if (!allow_custom_value && filtered_indices.length > 0) { + active_index = filtered_indices[0]; + } + } + } + + $: { + if (input_text !== old_input_text) { + filtered_indices = handle_filter(choices, input_text); old_input_text = input_text; if (!allow_custom_value && filtered_indices.length > 0) { active_index = filtered_indices[0];