Skip to content

Commit 035f9b0

Browse files
authored
ensure we compare raw values (#307)
1 parent 5ff5225 commit 035f9b0

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

packages/@headlessui-vue/src/components/radio-group/radio-group.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,58 @@ describe('Rendering', () => {
192192
`Pickup - ${JSON.stringify({ checked: false, active: false })}`
193193
)
194194
})
195+
196+
it('should set the checked v-slot info to true for the selected item (testing with objects, because Vue proxies)', async () => {
197+
renderTemplate({
198+
template: html`
199+
<RadioGroup v-model="deliveryMethod">
200+
<RadioGroupLabel>Pizza Delivery</RadioGroupLabel>
201+
<RadioGroupOption v-for="option in options" key="option.id" :value="option" v-slot="data"
202+
>{{option.label}} - {{JSON.stringify(data)}}</RadioGroupOption
203+
>
204+
</RadioGroup>
205+
`,
206+
setup() {
207+
let deliveryMethod = ref(undefined)
208+
let options = ref([
209+
{ id: 1, label: 'Pickup' },
210+
{ id: 2, label: 'Home delivery' },
211+
{ id: 3, label: 'Dine in' },
212+
])
213+
return { deliveryMethod, options }
214+
},
215+
})
216+
217+
await new Promise<void>(nextTick)
218+
219+
let [pickup, homeDelivery, dineIn] = Array.from(
220+
document.querySelectorAll('[id^="headlessui-radiogroup-option-"]')
221+
)
222+
expect(pickup).toHaveTextContent(
223+
`Pickup - ${JSON.stringify({ checked: false, active: false })}`
224+
)
225+
expect(homeDelivery).toHaveTextContent(
226+
`Home delivery - ${JSON.stringify({ checked: false, active: false })}`
227+
)
228+
expect(dineIn).toHaveTextContent(
229+
`Dine in - ${JSON.stringify({ checked: false, active: false })}`
230+
)
231+
232+
await click(homeDelivery)
233+
;[pickup, homeDelivery, dineIn] = Array.from(
234+
document.querySelectorAll('[id^="headlessui-radiogroup-option-"]')
235+
)
236+
237+
expect(pickup).toHaveTextContent(
238+
`Pickup - ${JSON.stringify({ checked: false, active: false })}`
239+
)
240+
expect(homeDelivery).toHaveTextContent(
241+
`Home delivery - ${JSON.stringify({ checked: true, active: true })}`
242+
)
243+
expect(dineIn).toHaveTextContent(
244+
`Dine in - ${JSON.stringify({ checked: false, active: false })}`
245+
)
246+
})
195247
})
196248

197249
describe('Keyboard interactions', () => {

packages/@headlessui-vue/src/components/radio-group/radio-group.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
onUnmounted,
88
provide,
99
ref,
10+
toRaw,
1011
watchEffect,
1112

1213
// Types
@@ -241,18 +242,17 @@ export let RadioGroupOption = defineComponent({
241242
let api = useRadioGroupContext('RadioGroupOption')
242243

243244
let firstRadio = api.options.value?.[0]?.id === this.id
244-
let checked = api.value.value === value
245245

246-
let slot = { checked, active: Boolean(this.state & OptionState.Active) }
246+
let slot = { checked: this.checked, active: Boolean(this.state & OptionState.Active) }
247247
let propsWeControl = {
248248
id: this.id,
249249
ref: 'el',
250250
role: 'radio',
251251
class: resolvePropValue(className, slot),
252-
'aria-checked': checked ? 'true' : 'false',
252+
'aria-checked': this.checked ? 'true' : 'false',
253253
'aria-labelledby': this.labelledby,
254254
'aria-describedby': this.describedby,
255-
tabIndex: checked ? 0 : api.value.value === undefined && firstRadio ? 0 : -1,
255+
tabIndex: this.checked ? 0 : api.value.value === undefined && firstRadio ? 0 : -1,
256256
onClick: this.handleClick,
257257
onFocus: this.handleFocus,
258258
onBlur: this.handleBlur,
@@ -291,6 +291,7 @@ export let RadioGroupOption = defineComponent({
291291
state,
292292
LabelProvider,
293293
DescriptionProvider,
294+
checked: computed(() => toRaw(api.value.value) === toRaw(props.value)),
294295
handleClick() {
295296
let value = props.value
296297
if (api.value.value === value) return

0 commit comments

Comments
 (0)