Skip to content

Commit cf78d97

Browse files
Resync input when display value changes (#1679)
* Resync input when display value changes * Update changelog
1 parent 0e1599b commit cf78d97

File tree

6 files changed

+121
-3
lines changed

6 files changed

+121
-3
lines changed

packages/@headlessui-react/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- Don’t close dialog when drag ends outside dialog ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
2020
- Fix outside clicks to close dialog when nested, unopened dialogs are present ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
2121
- Close `Menu` component when using `tab` key ([#1673](https://github.com/tailwindlabs/headlessui/pull/1673))
22+
- Resync input when display value changes ([#1679](https://github.com/tailwindlabs/headlessui/pull/1679))
2223

2324
## [1.6.6] - 2022-07-07
2425

packages/@headlessui-react/src/components/combobox/combobox.test.tsx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,70 @@ describe('Rendering', () => {
344344
})
345345
)
346346

347+
it(
348+
'conditionally rendering the input should allow changing the display value',
349+
suppressConsoleLogs(async () => {
350+
function Example() {
351+
let [value, setValue] = useState(null)
352+
353+
return (
354+
<>
355+
<Combobox value={value} onChange={setValue} nullable>
356+
{({ open }) => {
357+
if (!open) {
358+
return (
359+
<>
360+
<Combobox.Input
361+
onChange={NOOP}
362+
displayValue={(str?: string) => `${str?.toUpperCase() ?? ''} closed`}
363+
/>
364+
<Combobox.Button>Trigger</Combobox.Button>
365+
</>
366+
)
367+
}
368+
369+
return (
370+
<>
371+
<Combobox.Input
372+
onChange={NOOP}
373+
displayValue={(str?: string) => `${str?.toUpperCase() ?? ''} open`}
374+
/>
375+
<Combobox.Button>Trigger</Combobox.Button>
376+
<Combobox.Options>
377+
<Combobox.Option value="a">Option A</Combobox.Option>
378+
<Combobox.Option value="b">Option B</Combobox.Option>
379+
<Combobox.Option value="c">Option C</Combobox.Option>
380+
</Combobox.Options>
381+
</>
382+
)
383+
}}
384+
</Combobox>
385+
</>
386+
)
387+
}
388+
389+
render(<Example />)
390+
391+
expect(getComboboxInput()).toHaveValue(' closed')
392+
393+
await click(getComboboxButton())
394+
395+
assertComboboxList({ state: ComboboxState.Visible })
396+
397+
expect(getComboboxInput()).toHaveValue(' open')
398+
399+
await click(getComboboxOptions()[1])
400+
401+
expect(getComboboxInput()).toHaveValue('B closed')
402+
403+
await click(getComboboxButton())
404+
405+
assertComboboxList({ state: ComboboxState.Visible })
406+
407+
expect(getComboboxInput()).toHaveValue('B open')
408+
})
409+
)
410+
347411
it(
348412
'should be possible to override the `type` on the input',
349413
suppressConsoleLogs(async () => {

packages/@headlessui-react/src/components/combobox/combobox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ let ComboboxRoot = forwardRefWithAs(function Combobox<
445445
} else {
446446
data.inputRef.current.value = ''
447447
}
448-
}, [value, data.inputRef, inputPropsRef])
448+
}, [value, data.inputRef, inputPropsRef.current?.displayValue])
449449

450450
let selectOption = useEvent((id: string) => {
451451
let option = data.options.find((item) => item.id === id)

packages/@headlessui-vue/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- Don’t close dialog when drag ends outside dialog ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
2020
- Fix outside clicks to close dialog when nested, unopened dialogs are present ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
2121
- Close `Menu` component when using `tab` key ([#1673](https://github.com/tailwindlabs/headlessui/pull/1673))
22+
- Resync input when display value changes ([#1679](https://github.com/tailwindlabs/headlessui/pull/1679))
2223

2324
## [1.6.7] - 2022-07-12
2425

packages/@headlessui-vue/src/components/combobox/combobox.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,54 @@ describe('Rendering', () => {
376376
})
377377
)
378378

379+
it(
380+
'conditionally rendering the input should allow changing the display value',
381+
suppressConsoleLogs(async () => {
382+
let Example = defineComponent({
383+
template: html`
384+
<Combobox v-model="value" v-slot="{ open }" nullable>
385+
<template v-if="!open">
386+
<ComboboxInput :displayValue="(str) => (str?.toUpperCase() ?? '') + ' closed'" />
387+
<ComboboxButton>Trigger</ComboboxButton>
388+
</template>
389+
<template v-else>
390+
<ComboboxInput :displayValue="(str) => (str?.toUpperCase() ?? '') + ' open'" />
391+
<ComboboxButton>Trigger</ComboboxButton>
392+
<ComboboxOptions>
393+
<ComboboxOption value="a">Option A</ComboboxOption>
394+
<ComboboxOption value="b">Option B</ComboboxOption>
395+
<ComboboxOption value="c">Option C</ComboboxOption>
396+
</ComboboxOptions>
397+
</template>
398+
</Combobox>
399+
`,
400+
setup: () => ({ value: ref(null) }),
401+
})
402+
403+
renderTemplate(Example)
404+
405+
await nextFrame()
406+
407+
expect(getComboboxInput()).toHaveValue(' closed')
408+
409+
await click(getComboboxButton())
410+
411+
assertComboboxList({ state: ComboboxState.Visible })
412+
413+
expect(getComboboxInput()).toHaveValue(' open')
414+
415+
await click(getComboboxOptions()[1])
416+
417+
expect(getComboboxInput()).toHaveValue('B closed')
418+
419+
await click(getComboboxButton())
420+
421+
assertComboboxList({ state: ComboboxState.Visible })
422+
423+
expect(getComboboxInput()).toHaveValue('B open')
424+
})
425+
)
426+
379427
it(
380428
'should be possible to override the `type` on the input',
381429
suppressConsoleLogs(async () => {

packages/@headlessui-vue/src/components/combobox/combobox.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,9 @@ export let Combobox = defineComponent({
402402
computed(() => comboboxState.value === ComboboxStates.Open)
403403
)
404404

405-
watch([api.value, api.inputRef], () => api.syncInputValue(), {
405+
watch([api.value, api.inputRef, api.inputPropsRef], () => api.syncInputValue(), {
406406
immediate: true,
407+
deep: true,
407408
})
408409

409410
// Only sync the input value on close as typing into the input will trigger it to open
@@ -634,7 +635,10 @@ export let ComboboxInput = defineComponent({
634635
setup(props, { emit, attrs, slots, expose }) {
635636
let api = useComboboxContext('ComboboxInput')
636637
let id = `headlessui-combobox-input-${useId()}`
637-
api.inputPropsRef = computed(() => props)
638+
639+
watchEffect(() => {
640+
api.inputPropsRef.value = props
641+
})
638642

639643
expose({ el: api.inputRef, $el: api.inputRef })
640644

0 commit comments

Comments
 (0)