diff --git a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
index a4df3818a9..54c679482f 100644
--- a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
+++ b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
@@ -460,6 +460,46 @@ describe('Rendering', () => {
})
)
+ it(
+ 'selecting an option puts the display value into Combobox.Input when displayValue is provided (when value is undefined)',
+ suppressConsoleLogs(async () => {
+ function Example() {
+ let [value, setValue] = useState(undefined)
+
+ return (
+
+ str?.toUpperCase() ?? ''}
+ />
+ Trigger
+
+ Option A
+ Option B
+ Option C
+
+
+ )
+ }
+
+ render()
+
+ // Focus the input
+ await focus(getComboboxInput())
+
+ // Type in it
+ await type(word('A'), getComboboxInput())
+
+ // Stop typing (and clear the input)
+ await press(Keys.Escape, getComboboxInput())
+
+ // Focus the body (so the input loses focus)
+ await focus(document.body)
+
+ expect(getComboboxInput()).toHaveValue('')
+ })
+ )
+
it(
'conditionally rendering the input should allow changing the display value',
suppressConsoleLogs(async () => {
diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md
index 1cab876079..17a84b8414 100644
--- a/packages/@headlessui-vue/CHANGELOG.md
+++ b/packages/@headlessui-vue/CHANGELOG.md
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
-- Nothing yet!
+### Fixed
+
+- Call `displayValue` with a v-model of `ref(undefined)` on `ComboboxInput` ([#1865](https://github.com/tailwindlabs/headlessui/pull/1865))
## [1.7.2] - 2022-09-15
diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.test.ts b/packages/@headlessui-vue/src/components/combobox/combobox.test.ts
index a7c7b21b30..0bbf63e00e 100644
--- a/packages/@headlessui-vue/src/components/combobox/combobox.test.ts
+++ b/packages/@headlessui-vue/src/components/combobox/combobox.test.ts
@@ -493,6 +493,43 @@ describe('Rendering', () => {
})
)
+ // This really is a bug in Vue but we have a workaround for it
+ it(
+ 'selecting an option puts the display value into Combobox.Input when displayValue is provided (when v-model is undefined)',
+ suppressConsoleLogs(async () => {
+ let Example = defineComponent({
+ template: html`
+
+
+ Trigger
+
+ Option A
+ Option B
+ Option C
+
+
+ `,
+ setup: () => ({ value: ref(undefined) }),
+ })
+
+ renderTemplate(Example)
+
+ // Focus the input
+ await focus(getComboboxInput())
+
+ // Type in it
+ await type(word('A'), getComboboxInput())
+
+ // Stop typing (and clear the input)
+ await press(Keys.Escape, getComboboxInput())
+
+ // Focus the body (so the input loses focus)
+ await focus(document.body)
+
+ expect(getComboboxInput()).toHaveValue('')
+ })
+ )
+
it('conditionally rendering the input should allow changing the display value', async () => {
let Example = defineComponent({
template: html`
diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.ts b/packages/@headlessui-vue/src/components/combobox/combobox.ts
index 157255ae4a..d287ac7cbd 100644
--- a/packages/@headlessui-vue/src/components/combobox/combobox.ts
+++ b/packages/@headlessui-vue/src/components/combobox/combobox.ts
@@ -629,11 +629,20 @@ export let ComboboxInput = defineComponent({
}
}
+ // Workaround Vue bug where watching [ref(undefined)] is not fired immediately even when value is true
+ const __fixVueImmediateWatchBug__ = ref('')
+
onMounted(() => {
- watch([api.value], () => (currentValue.value = getCurrentValue()), {
- flush: 'sync',
- immediate: true,
- })
+ watch(
+ [api.value, __fixVueImmediateWatchBug__],
+ () => {
+ currentValue.value = getCurrentValue()
+ },
+ {
+ flush: 'sync',
+ immediate: true,
+ }
+ )
watch(
[currentValue, api.comboboxState],