Skip to content

Commit

Permalink
Resync input when display value changes (#1679)
Browse files Browse the repository at this point in the history
* Resync input when display value changes

* Update changelog
  • Loading branch information
thecrypticace authored Jul 15, 2022
1 parent 0e1599b commit cf78d97
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 3 deletions.
1 change: 1 addition & 0 deletions packages/@headlessui-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Don’t close dialog when drag ends outside dialog ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
- Fix outside clicks to close dialog when nested, unopened dialogs are present ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
- Close `Menu` component when using `tab` key ([#1673](https://github.com/tailwindlabs/headlessui/pull/1673))
- Resync input when display value changes ([#1679](https://github.com/tailwindlabs/headlessui/pull/1679))

## [1.6.6] - 2022-07-07

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,70 @@ describe('Rendering', () => {
})
)

it(
'conditionally rendering the input should allow changing the display value',
suppressConsoleLogs(async () => {
function Example() {
let [value, setValue] = useState(null)

return (
<>
<Combobox value={value} onChange={setValue} nullable>
{({ open }) => {
if (!open) {
return (
<>
<Combobox.Input
onChange={NOOP}
displayValue={(str?: string) => `${str?.toUpperCase() ?? ''} closed`}
/>
<Combobox.Button>Trigger</Combobox.Button>
</>
)
}

return (
<>
<Combobox.Input
onChange={NOOP}
displayValue={(str?: string) => `${str?.toUpperCase() ?? ''} open`}
/>
<Combobox.Button>Trigger</Combobox.Button>
<Combobox.Options>
<Combobox.Option value="a">Option A</Combobox.Option>
<Combobox.Option value="b">Option B</Combobox.Option>
<Combobox.Option value="c">Option C</Combobox.Option>
</Combobox.Options>
</>
)
}}
</Combobox>
</>
)
}

render(<Example />)

expect(getComboboxInput()).toHaveValue(' closed')

await click(getComboboxButton())

assertComboboxList({ state: ComboboxState.Visible })

expect(getComboboxInput()).toHaveValue(' open')

await click(getComboboxOptions()[1])

expect(getComboboxInput()).toHaveValue('B closed')

await click(getComboboxButton())

assertComboboxList({ state: ComboboxState.Visible })

expect(getComboboxInput()).toHaveValue('B open')
})
)

it(
'should be possible to override the `type` on the input',
suppressConsoleLogs(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ let ComboboxRoot = forwardRefWithAs(function Combobox<
} else {
data.inputRef.current.value = ''
}
}, [value, data.inputRef, inputPropsRef])
}, [value, data.inputRef, inputPropsRef.current?.displayValue])

let selectOption = useEvent((id: string) => {
let option = data.options.find((item) => item.id === id)
Expand Down
1 change: 1 addition & 0 deletions packages/@headlessui-vue/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Don’t close dialog when drag ends outside dialog ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
- Fix outside clicks to close dialog when nested, unopened dialogs are present ([#1667](https://github.com/tailwindlabs/headlessui/pull/1667))
- Close `Menu` component when using `tab` key ([#1673](https://github.com/tailwindlabs/headlessui/pull/1673))
- Resync input when display value changes ([#1679](https://github.com/tailwindlabs/headlessui/pull/1679))

## [1.6.7] - 2022-07-12

Expand Down
48 changes: 48 additions & 0 deletions packages/@headlessui-vue/src/components/combobox/combobox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,54 @@ describe('Rendering', () => {
})
)

it(
'conditionally rendering the input should allow changing the display value',
suppressConsoleLogs(async () => {
let Example = defineComponent({
template: html`
<Combobox v-model="value" v-slot="{ open }" nullable>
<template v-if="!open">
<ComboboxInput :displayValue="(str) => (str?.toUpperCase() ?? '') + ' closed'" />
<ComboboxButton>Trigger</ComboboxButton>
</template>
<template v-else>
<ComboboxInput :displayValue="(str) => (str?.toUpperCase() ?? '') + ' open'" />
<ComboboxButton>Trigger</ComboboxButton>
<ComboboxOptions>
<ComboboxOption value="a">Option A</ComboboxOption>
<ComboboxOption value="b">Option B</ComboboxOption>
<ComboboxOption value="c">Option C</ComboboxOption>
</ComboboxOptions>
</template>
</Combobox>
`,
setup: () => ({ value: ref(null) }),
})

renderTemplate(Example)

await nextFrame()

expect(getComboboxInput()).toHaveValue(' closed')

await click(getComboboxButton())

assertComboboxList({ state: ComboboxState.Visible })

expect(getComboboxInput()).toHaveValue(' open')

await click(getComboboxOptions()[1])

expect(getComboboxInput()).toHaveValue('B closed')

await click(getComboboxButton())

assertComboboxList({ state: ComboboxState.Visible })

expect(getComboboxInput()).toHaveValue('B open')
})
)

it(
'should be possible to override the `type` on the input',
suppressConsoleLogs(async () => {
Expand Down
8 changes: 6 additions & 2 deletions packages/@headlessui-vue/src/components/combobox/combobox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,9 @@ export let Combobox = defineComponent({
computed(() => comboboxState.value === ComboboxStates.Open)
)

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

// Only sync the input value on close as typing into the input will trigger it to open
Expand Down Expand Up @@ -634,7 +635,10 @@ export let ComboboxInput = defineComponent({
setup(props, { emit, attrs, slots, expose }) {
let api = useComboboxContext('ComboboxInput')
let id = `headlessui-combobox-input-${useId()}`
api.inputPropsRef = computed(() => props)

watchEffect(() => {
api.inputPropsRef.value = props
})

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

Expand Down

0 comments on commit cf78d97

Please sign in to comment.