diff --git a/ui/src/dropdown.test.tsx b/ui/src/dropdown.test.tsx index 35bb51cbdb2..ff7846f8bde 100644 --- a/ui/src/dropdown.test.tsx +++ b/ui/src/dropdown.test.tsx @@ -708,6 +708,28 @@ describe('Dropdown.tsx', () => { rerender() expect(wave.args[name]).toEqual('1') }) + + it('Updates choices of single-valued dialog dropdown', () => { + const + choices = [{ name: 'A', label: 'Choice A' }], + updatedChoices = [ + { name: 'D', label: 'Choice D' }, + { name: 'E', label: 'Choice E' }, + { name: 'F', label: 'Choice F' }, + ], + { getByTestId, getByText, queryByText, rerender } = render() + + fireEvent.click(getByTestId(name)) + expect(getByText('Choice A')).toBeInTheDocument() + + rerender() + fireEvent.click(getByTestId(name)) + + expect(queryByText('Choice A')).not.toBeInTheDocument() + expect(getByText('Choice D')).toBeInTheDocument() + expect(getByText('Choice E')).toBeInTheDocument() + expect(getByText('Choice F')).toBeInTheDocument() + }) }) describe('Multi-valued', () => { @@ -804,6 +826,28 @@ describe('Dropdown.tsx', () => { expect(checkboxes[0]).toBeChecked() expect(checkboxes[1]).toBeChecked() }) + + it('Updates choices of multi-valued dialog dropdown', () => { + const + choices = [{ name: 'A', label: 'Choice A' }], + updatedChoices = [ + { name: 'D', label: 'Choice D' }, + { name: 'E', label: 'Choice E' }, + { name: 'F', label: 'Choice F' }, + ], + { getByTestId, getByText, queryByText, rerender } = render() + + fireEvent.click(getByTestId(name)) + expect(getByText('Choice A')).toBeInTheDocument() + + rerender() + fireEvent.click(getByTestId(name)) + + expect(queryByText('Choice A')).not.toBeInTheDocument() + expect(getByText('Choice D')).toBeInTheDocument() + expect(getByText('Choice E')).toBeInTheDocument() + expect(getByText('Choice F')).toBeInTheDocument() + }) }) }) }) diff --git a/ui/src/dropdown.tsx b/ui/src/dropdown.tsx index d2d1601391d..016ef005150 100644 --- a/ui/src/dropdown.tsx +++ b/ui/src/dropdown.tsx @@ -168,11 +168,11 @@ const ROW_HEIGHT = 44, PAGE_SIZE = 40, getPageSpecification = () => ({ itemCount: PAGE_SIZE, height: ROW_HEIGHT * PAGE_SIZE } as Fluent.IPageSpecification), + choicesToItems = (choices: Choice[], v?: S | S[]) => choices.map(({ name, label, disabled = false }, idx) => + ({ name, text: label || name, idx, checked: Array.isArray(v) ? v.includes(name) : v === name, show: true, disabled })), useItems = (choices: Choice[], v?: S | S[]) => { - const - [items, setItems] = React.useState(choices.map(({ name, label, disabled = false }, idx) => - ({ name, text: label || name, idx, checked: Array.isArray(v) ? v.includes(name) : v === name, show: true, disabled }))), - onSearchChange = (_e?: React.ChangeEvent, newVal = '') => setItems(items => items.map(i => ({ ...i, show: fuzzysearch(i.text, newVal) }))) + const [items, setItems] = React.useState(choicesToItems(choices, v)) + const onSearchChange = (_e?: React.ChangeEvent, newVal = '') => setItems(items => items.map(i => ({ ...i, show: fuzzysearch(i.text, newVal) }))) return [items, setItems, onSearchChange] as const }, @@ -206,11 +206,9 @@ const } React.useEffect(() => { - if (model.value !== undefined) { - wave.args[name] = model.value ?? null - setItems(items => items.map(i => ({ ...i, checked: model.value === i.name }))) - } - }, [name, model.value, setItems]) + wave.args[name] = model.value ?? null + setItems(choicesToItems(choices, model.value)) + }, [name, model.value, choices, setItems]) return ( <> @@ -274,11 +272,9 @@ const } React.useEffect(() => { - if (values) { - wave.args[name] = values - setItems(items => items.map(i => ({ ...i, checked: values.includes(i.name) }))) - } - }, [name, values, setItems]) + wave.args[name] = values + setItems(choicesToItems(choices, values)) + }, [name, values, choices, setItems]) return ( <>