Skip to content

Commit

Permalink
Ensure ComboboxInput syncs correctly (#1106)
Browse files Browse the repository at this point in the history
* ensure ComboboxInput syncs correctly

* update changelog
  • Loading branch information
RobinMalfait authored Feb 15, 2022
1 parent 639d8d2 commit 0bf325d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 59 deletions.
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Add `Combobox` component ([#1047](https://github.com/tailwindlabs/headlessui/pull/1047), [#1099](https://github.com/tailwindlabs/headlessui/pull/1099), [#1101](https://github.com/tailwindlabs/headlessui/pull/1101), - Bubble Escape event even if `Combobox.Options` is not rendered at all ()
)
- Add `Combobox` component ([#1047](https://github.com/tailwindlabs/headlessui/pull/1047), [#1099](https://github.com/tailwindlabs/headlessui/pull/1099), [#1101](https://github.com/tailwindlabs/headlessui/pull/1101), [#1104](https://github.com/tailwindlabs/headlessui/pull/1104), [#1106](https://github.com/tailwindlabs/headlessui/pull/1106))

## [@headlessui/react@v1.4.3] - 2022-01-14

Expand Down
22 changes: 10 additions & 12 deletions packages/@headlessui-vue/src/components/combobox/combobox.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import {
computed,
defineComponent,
ref,
provide,
inject,
nextTick,
onMounted,
onUnmounted,
computed,
nextTick,
InjectionKey,
Ref,
ComputedRef,
watchEffect,
provide,
ref,
toRaw,
watch,
watchEffect,
ComputedRef,
InjectionKey,
PropType,
Ref,
} from 'vue'

import { Features, render, omit } from '../../utils/render'
Expand Down Expand Up @@ -232,9 +232,7 @@ export let Combobox = defineComponent({
api.closeCombobox()
})

watchEffect(() => {
api.syncInputValue()
})
watch([api.value, api.inputRef], () => api.syncInputValue(), { immediate: true })

// @ts-expect-error Types of property 'dataRef' are incompatible.
provide(ComboboxContext, api)
Expand Down Expand Up @@ -525,7 +523,7 @@ export let ComboboxInput = defineComponent({
tabIndex: 0,
ref: api.inputRef,
}
let passThroughProps = props
let passThroughProps = omit(props, ['displayValue'])

return render({
props: { ...passThroughProps, ...propsWeControl },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,18 @@ import {
} from '@headlessui/vue'
let everybody = [
'Wade Cooper',
'Arlene Mccoy',
'Devon Webb',
'Tom Cook',
'Tanya Fox',
'Hellen Schmidt',
'Caroline Schultz',
'Mason Heaney',
'Claudie Smitham',
'Emil Schaefer',
{ id: 1, name: 'Wade Cooper' },
{ id: 2, name: 'Arlene Mccoy' },
{ id: 3, name: 'Devon Webb' },
{ id: 4, name: 'Tom Cook' },
{ id: 5, name: 'Tanya Fox' },
{ id: 6, name: 'Hellen Schmidt' },
{ id: 7, name: 'Caroline Schultz' },
{ id: 8, name: 'Mason Heaney' },
{ id: 9, name: 'Claudie Smitham' },
{ id: 10, name: 'Emil Schaefer' },
]
/**
* @template T
* @param {Ref<T>} value
* @param {number} delay
*/
function useDebounce(value, delay) {
let debouncedValue = ref(value.value)
let timer
return computed({
get() {
return debouncedValue.value
},
set(newValue) {
timer && clearTimeout(timer)
timer = setTimeout(() => (debouncedValue.value = newValue), delay)
},
})
}
export default defineComponent({
components: {
Combobox,
Expand All @@ -54,27 +33,30 @@ export default defineComponent({
},
setup() {
let query = ref('')
let activePerson = ref(everybody[2])
// Mimic delayed response from an API
let actualQuery = useDebounce(
query,
0 /* Change to higher value like 100 for testing purposes */
)
let activePerson = ref(null) // everybody[Math.floor(Math.random() * everybody.length)]
let filteredPeople = computed(() => {
return query.value === ''
? everybody
: everybody.filter((person) => {
return person.name.toLowerCase().includes(query.value.toLowerCase())
})
})
return {
query,
activePerson,
everybody,
actualQuery,
filteredPeople,
}
},
})
</script>

<template>
<div class="flex h-full w-screen justify-center bg-gray-50 p-12">
<div class="mx-auto w-full max-w-xs">
<div class="py-8 font-mono text-xs">Selected person: {{ activePerson }}</div>
<div class="py-8 font-mono text-xs">
Selected person: {{ activePerson?.name ?? 'Nobody yet' }}
</div>
<div class="space-y-1">
<Combobox v-model="activePerson" as="div">
<ComboboxLabel class="block text-sm font-medium leading-5 text-gray-700">
Expand All @@ -85,6 +67,7 @@ export default defineComponent({
<span class="relative inline-flex flex-row overflow-hidden rounded-md border shadow-sm">
<ComboboxInput
@change="query = $event.target.value"
:displayValue="(person) => person?.name ?? ''"
class="border-none px-3 py-1 outline-none"
/>
<ComboboxButton
Expand Down Expand Up @@ -113,9 +96,9 @@ export default defineComponent({
class="shadow-xs max-h-60 overflow-auto rounded-md py-1 text-base leading-6 focus:outline-none sm:text-sm sm:leading-5"
>
<ComboboxOption
v-for="name in everybody"
:key="name"
:value="name"
v-for="person in filteredPeople"
:key="person.id"
:value="person"
v-slot="{ active, selected }"
>
<div
Expand All @@ -125,7 +108,7 @@ export default defineComponent({
]"
>
<span :class="['block truncate', selected ? 'font-semibold' : 'font-normal']">
{{ name }}
{{ person.name }}
</span>
<span
v-if="selected"
Expand Down

0 comments on commit 0bf325d

Please sign in to comment.