fix(components): [radio] the id attribute acts on the input

This commit is contained in:
Xc 2022-06-25 19:39:15 +08:00
parent f86a793c29
commit f6ec6c963a
5 changed files with 131 additions and 9 deletions

View File

@ -315,11 +315,10 @@ describe('Radio Button', () => {
const formItem = await wrapper.findComponent(ElFormItem)
const radioGroup = await wrapper.findComponent(RadioGroup)
const formItemLabel = formItem.find('.el-form-item__label')
expect(formItem.attributes().role).toBeFalsy()
expect(formItem.attributes().role).toBe('group')
expect(radioGroup.attributes().role).toBe('radiogroup')
expect(formItemLabel.attributes().for).toBe(radioGroup.attributes().id)
expect(formItemLabel.attributes().id).toBe(
radioGroup.attributes()['aria-labelledby']
formItem.attributes()['aria-labelledby']
)
})
@ -336,7 +335,9 @@ describe('Radio Button', () => {
const formItem = await wrapper.findComponent(ElFormItem)
const radioGroup = await wrapper.findComponent(RadioGroup)
const formItemLabel = formItem.find('.el-form-item__label')
expect(formItemLabel.attributes().for).toBe(radioGroup.attributes().id)
expect(formItemLabel.attributes().id).toBe(
formItem.attributes()['aria-labelledby']
)
expect(radioGroup.attributes().role).toBe('radiogroup')
expect(radioGroup.attributes()['aria-label']).toBe('Foo')
expect(radioGroup.attributes()['aria-labelledby']).toBeFalsy()
@ -374,3 +375,99 @@ describe('Radio Button', () => {
})
})
})
describe('laebl for', () => {
test('label and radio', async () => {
const radio = ref('')
const forId = ref('radio1121')
const wrapper = mount(() => (
<>
<label for={forId.value}>click here</label>
<Radio v-model={radio.value} label="Foo" id="radio1121" />
</>
))
await nextTick()
const label = wrapper.find('label')
label.trigger('click')
expect(radio.value).toBe('Foo')
// no for
radio.value = ''
forId.value = undefined
await nextTick()
label.trigger('click')
expect(radio.value).toBe('')
})
test('label and radioGroup', async () => {
const compList = [Radio, RadioButton]
compList.forEach(async (comp) => {
const radio = ref('')
const forId = ref('radio1121')
const wrapper = mount(() => (
<>
<label for={forId.value}>click here</label>
<RadioGroup v-model={radio.value}>
<comp label="Foo" id="radio1121" />
<comp label="Bar" id="radio1122" />
</RadioGroup>
</>
))
await nextTick()
const label = wrapper.find('label')
label.trigger('click')
expect(radio.value).toBe('Foo')
// no for
radio.value = ''
forId.value = undefined
await nextTick()
label.trigger('click')
expect(radio.value).toBe('')
})
})
test('form-item label and radio', async () => {
const radio = ref('')
const wrapper = mount(() => (
<ElFormItem label="test">
<Radio v-model={radio.value} label="Foo" />
</ElFormItem>
))
await nextTick()
const label = wrapper.find('.el-form-item__label')
label.trigger('click')
expect(radio.value).toBe('Foo')
})
test('form-item label and radio multiple', async () => {
const radio = ref('')
const wrapper = mount(() => (
<ElFormItem label="test">
<Radio v-model={radio.value} label="Foo" />
<Radio v-model={radio.value} label="Bar" />
</ElFormItem>
))
await nextTick()
const label = wrapper.find('.el-form-item__label')
label.trigger('click')
expect(radio.value).toBe('')
})
test('form-item label and radioGroup', async () => {
const compList = [Radio, RadioButton]
compList.forEach(async (comp) => {
const radio = ref('')
const wrapper = mount(() => (
<ElFormItem label="test">
<RadioGroup v-model={radio.value}>
<comp label="Foo" id="radio1121" />
<comp label="Bar" id="radio1122" />
</RadioGroup>
</ElFormItem>
))
await nextTick()
const label = wrapper.find('.el-form-item__label')
label.trigger('click')
expect(radio.value).toBe('')
})
})
})

View File

@ -5,6 +5,10 @@ import type RadioButton from './radio-button.vue'
export const radioButtonProps = buildProps({
...radioPropsBase,
id: {
type: String,
default: undefined,
},
name: {
type: String,
default: '',

View File

@ -9,6 +9,7 @@
]"
>
<input
:id="inputId"
ref="radioRef"
v-model="modelValue"
:class="ns.be('button', 'original-radio')"
@ -33,7 +34,11 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useNamespace } from '@element-plus/hooks'
import {
useFormItem,
useFormItemInputId,
useNamespace,
} from '@element-plus/hooks'
import { useRadio } from './use-radio'
import { radioButtonProps } from './radio-button'
import type { CSSProperties } from 'vue'
@ -44,6 +49,11 @@ defineOptions({
const props = defineProps(radioButtonProps)
const { formItem } = useFormItem()
const { inputId } = useFormItemInputId(props, {
formItemContext: formItem,
})
const ns = useNamespace('radio')
const { radioRef, focus, size, disabled, modelValue, radioGroup } =
useRadio(props)

View File

@ -15,6 +15,10 @@ export const radioPropsBase = buildProps({
export const radioProps = buildProps({
...radioPropsBase,
id: {
type: String,
default: undefined,
},
modelValue: {
type: [String, Number, Boolean],
default: '',

View File

@ -8,7 +8,6 @@
ns.is('checked', modelValue === label),
ns.m(size),
]"
v-bind="{ ...$attrs, id: undefined }"
>
<span
:class="[
@ -18,7 +17,7 @@
]"
>
<input
:id="$attrs.id as string"
:id="inputId"
ref="radioRef"
v-model="modelValue"
:class="ns.e('original')"
@ -42,18 +41,26 @@
<script lang="ts" setup>
import { nextTick } from 'vue'
import { useNamespace } from '@element-plus/hooks'
import {
useFormItem,
useFormItemInputId,
useNamespace,
} from '@element-plus/hooks'
import { radioEmits, radioProps } from './radio'
import { useRadio } from './use-radio'
defineOptions({
name: 'ElRadio',
inheritAttrs: false,
})
const props = defineProps(radioProps)
const emit = defineEmits(radioEmits)
const { formItem } = useFormItem()
const { inputId } = useFormItemInputId(props, {
formItemContext: formItem,
})
const ns = useNamespace('radio')
const { radioRef, radioGroup, focus, size, disabled, modelValue } = useRadio(
props,