feat(components): [checkbox & radio] Use value instead of label act as value (#15525)

* feat(components): [checkbox & radio] Use value instead of label

* feat(components): update

* feat(components): update

* feat(components): update

* feat(components): update

* feat(components): update

* feat(components): update test

* feat(components): true-value false-value

* feat(components): update
This commit is contained in:
kooriookami 2024-02-28 12:48:07 +08:00 committed by GitHub
parent d8a9f902b2
commit 3ca4473aeb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 424 additions and 278 deletions

View File

@ -5,6 +5,14 @@ lang: en-US
# Checkbox
:::warning
`label` act as `value` has been **deprecated**, `label` is used only as display text, this action **will be** removed in ^(3.0.0), consider switching to new API.
New API `value` has been added in ^(2.6.0), you can use `value` API to set the value of Checkbox.
:::
A group of options for multiple choices.
## Basic usage
@ -31,7 +39,7 @@ checkbox/disabled
It is used for multiple checkboxes which are bound in one group, and indicates whether one option is selected by checking if it is checked.
:::demo `checkbox-group` element can manage multiple checkboxes in one group by using `v-model` which is bound as an `Array`. Inside the `el-checkbox` element, `label` is the value of the checkbox. If no content is nested in that tag, `label` will be rendered as the description following the button of the checkbox. `label` also corresponds with the element values in the array. It is selected if the specified value exists in the array, and vice versa.
:::demo `checkbox-group` element can manage multiple checkboxes in one group by using `v-model` which is bound as an `Array`. Inside the `el-checkbox` element, `value` is the value of the checkbox. If no content is nested in that tag, `label` will be rendered as the description following the button of the checkbox. `value` also corresponds with the element values in the array. It is selected if the specified value exists in the array, and vice versa.
checkbox/grouping
@ -79,22 +87,25 @@ checkbox/with-border
### Checkbox Attributes
| Name | Description | Type | Default |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ------- |
| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] | — |
| label | value of the Checkbox when used inside a `checkbox-group` | ^[string] / ^[number] / ^[boolean] / ^[object] | — |
| true-label | value of the Checkbox if it's checked | ^[string] / ^[number] | — |
| false-label | value of the Checkbox if it's not checked | ^[string] / ^[number] | — |
| disabled | whether the Checkbox is disabled | ^[boolean] | false |
| border | whether to add a border around Checkbox | ^[boolean] | false |
| size | size of the Checkbox | ^[enum]`'large' \| 'default' \| 'small'` | — |
| name | native 'name' attribute | ^[string] | — |
| checked | if the Checkbox is checked | ^[boolean] | false |
| indeterminate | Set indeterminate state, only responsible for style control | ^[boolean] | false |
| validate-event | whether to trigger form validation | ^[boolean] | true |
| tabindex | input tabindex | ^[string] / ^[number] | — |
| id | input id | ^[string] | — |
| controls ^(a11y) | same as [aria-controls](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls), takes effect when `indeterminate` is `true` | ^[boolean] | — |
| Name | Description | Type | Default |
|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|---------|
| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] | — |
| value ^(2.6.0) | value of the Checkbox when used inside a `checkbox-group` | ^[string] / ^[number] / ^[boolean] / ^[object] | — |
| label | label of the Checkbox when used inside a `checkbox-group`. If there's no value, `label` will act as `value` | ^[string] / ^[number] / ^[boolean] / ^[object] | — |
| true-value ^(2.6.0) | value of the Checkbox if it's checked | ^[string] / ^[number] | — |
| false-value ^(2.6.0) | value of the Checkbox if it's not checked | ^[string] / ^[number] | — |
| true-label ^(deprecated) | value of the Checkbox if it's checked | ^[string] / ^[number] | — |
| false-label ^(deprecated) | value of the Checkbox if it's not checked | ^[string] / ^[number] | — |
| disabled | whether the Checkbox is disabled | ^[boolean] | false |
| border | whether to add a border around Checkbox | ^[boolean] | false |
| size | size of the Checkbox | ^[enum]`'large' \| 'default' \| 'small'` | — |
| name | native 'name' attribute | ^[string] | — |
| checked | if the Checkbox is checked | ^[boolean] | false |
| indeterminate | Set indeterminate state, only responsible for style control | ^[boolean] | false |
| validate-event | whether to trigger form validation | ^[boolean] | true |
| tabindex | input tabindex | ^[string] / ^[number] | — |
| id | input id | ^[string] | — |
| controls ^(a11y) | same as [aria-controls](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls), takes effect when `indeterminate` is `true` | ^[boolean] | — |
### Checkbox Events
@ -113,7 +124,7 @@ checkbox/with-border
### CheckboxGroup Attributes
| Name | Description | Type | Default |
| --------------------- | ------------------------------------------------- | ---------------------------------------- | ------- |
|-----------------------|---------------------------------------------------|------------------------------------------|---------|
| model-value / v-model | binding value | ^[object]`string[] \| number[]` | [] |
| size | size of checkbox | ^[enum]`'large' \| 'default' \| 'small'` | — |
| disabled | whether the nesting checkboxes are disabled | ^[boolean] | false |
@ -141,14 +152,17 @@ checkbox/with-border
### CheckboxButton Attributes
| Name | Description | Type | Default |
| ----------- | --------------------------------------------------------- | ---------------------------------------------- | ------- |
| label | value of the checkbox when used inside a `checkbox-group` | ^[string] / ^[number] / ^[boolean] / ^[object] | — |
| true-label | value of the checkbox if it's checked | ^[string] / ^[number] | — |
| false-label | value of the checkbox if it's not checked | ^[string] / ^[number] | — |
| disabled | whether the checkbox is disabled | ^[boolean] | false |
| name | native 'name' attribute | ^[string] | — |
| checked | if the checkbox is checked | ^[boolean] | false |
| Name | Description | Type | Default |
|---------------------------|-------------------------------------------------------------------------------------------------------------|------------------------------------------------|---------|
| value ^(2.6.0) | value of the checkbox when used inside a `checkbox-group` | ^[string] / ^[number] / ^[boolean] / ^[object] | — |
| label | label of the checkbox when used inside a `checkbox-group`. If there's no value, `label` will act as `value` | ^[string] / ^[number] / ^[boolean] / ^[object] | — |
| true-value ^(2.6.0) | value of the checkbox if it's checked | ^[string] / ^[number] | — |
| false-value ^(2.6.0) | value of the checkbox if it's not checked | ^[string] / ^[number] | — |
| true-label ^(deprecated) | value of the checkbox if it's checked | ^[string] / ^[number] | — |
| false-label ^(deprecated) | value of the checkbox if it's not checked | ^[string] / ^[number] | — |
| disabled | whether the checkbox is disabled | ^[boolean] | false |
| name | native 'name' attribute | ^[string] | — |
| checked | if the checkbox is checked | ^[boolean] | false |
### CheckboxButton Slots

View File

@ -5,13 +5,21 @@ lang: en-US
# Radio
:::warning
`label` act as `value` has been **deprecated**, `label` is used only as display text, this action **will be** removed in ^(3.0.0), consider switching to new API.
New API `value` has been added in ^(2.6.0), you can use `value` API to set the value of Radio.
:::
Single selection among multiple options.
## Basic usage
Radio should not have too many options. Otherwise, use the Select component instead.
:::demo Creating a radio component is easy, you just need to bind a variable to Radio's `v-model`. It equals to the value of `label` of the chosen radio. The type of `label` is `String`, `Number` or `Boolean`.
:::demo Creating a radio component is easy, you just need to bind a variable to Radio's `v-model`. It equals to the value of `value` of the chosen radio. The type of `value` is `String`, `Number` or `Boolean`.
radio/basic-usage
@ -59,14 +67,15 @@ radio/with-borders
### Radio Attributes
| Name | Description | Type | Default |
| --------------------- | ------------------------------------ | ---------------------------------------- | ------- |
| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] | — |
| label | the value of Radio | ^[string] / ^[number] / ^[boolean] | — |
| disabled | whether Radio is disabled | ^[boolean] | false |
| border | whether to add a border around Radio | ^[boolean] | false |
| size | size of the Radio | ^[enum]`'large' \| 'default' \| 'small'` | — |
| name | native `name` attribute | ^[string] | — |
| Name | Description | Type | Default |
|-----------------------|------------------------------------------------------------------------|------------------------------------------|---------|
| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] | — |
| value ^(2.6.0) | the value of Radio | ^[string] / ^[number] / ^[boolean] | — |
| label | the label of Radio. If there's no `value`, `label` will act as `value` | ^[string] / ^[number] / ^[boolean] | — |
| disabled | whether Radio is disabled | ^[boolean] | false |
| border | whether to add a border around Radio | ^[boolean] | false |
| size | size of the Radio | ^[enum]`'large' \| 'default' \| 'small'` | — |
| name | native `name` attribute | ^[string] | — |
### Radio Events
@ -85,7 +94,7 @@ radio/with-borders
### RadioGroup Attributes
| Name | Description | Type | Default |
| --------------------- | ------------------------------------------------- | ---------------------------------- | ------- |
|-----------------------|---------------------------------------------------|------------------------------------|---------|
| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] | — |
| size | the size of radio buttons or bordered radios | ^[string] | default |
| disabled | whether the nesting radios are disabled | ^[boolean] | false |
@ -112,11 +121,12 @@ radio/with-borders
### RadioButton Attributes
| Name | Description | Type | Default |
| -------- | ------------------------- | ---------------------------------- | ------- |
| label | the value of Radio | ^[string] / ^[number] / ^[boolean] | — |
| disabled | whether Radio is disabled | ^[boolean] | false |
| name | native 'name' attribute | ^[string] | — |
| Name | Description | Type | Default |
|----------------|------------------------------------------------------------------------|------------------------------------|---------|
| value ^(2.6.0) | the value of Radio | ^[string] / ^[number] / ^[boolean] | — |
| label | the label of Radio. If there's no `value`, `label` will act as `value` | ^[string] / ^[number] / ^[boolean] | — |
| disabled | whether Radio is disabled | ^[boolean] | false |
| name | native 'name' attribute | ^[string] | — |
### RadioButton Slots

View File

@ -12,8 +12,8 @@
<el-checkbox v-model="checked6" label="Option 2" size="small" />
</div>
<div>
<el-checkbox v-model="checked5" label="Option 1" size="small" disabled />
<el-checkbox v-model="checked6" label="Option 2" size="small" disabled />
<el-checkbox v-model="checked7" label="Option 1" size="small" disabled />
<el-checkbox v-model="checked8" label="Option 2" size="small" disabled />
</div>
</template>
@ -26,4 +26,6 @@ const checked3 = ref(false)
const checked4 = ref(false)
const checked5 = ref(false)
const checked6 = ref(false)
const checked7 = ref(false)
const checked8 = ref(false)
</script>

View File

@ -1,16 +1,25 @@
<template>
<div>
<el-checkbox-group v-model="checkboxGroup1" size="large">
<el-checkbox-button v-for="city in cities" :key="city" :label="city">
<el-checkbox-button
v-for="city in cities"
:key="city"
:label="city"
:value="city"
>
{{ city }}
</el-checkbox-button>
</el-checkbox-group>
</div>
<div class="demo-button-style">
<el-checkbox-group v-model="checkboxGroup2">
<el-checkbox-button v-for="city in cities" :key="city" :label="city">{{
city
}}</el-checkbox-button>
<el-checkbox-button
v-for="city in cities"
:key="city"
:label="city"
:value="city"
>{{ city }}</el-checkbox-button
>
</el-checkbox-group>
</div>
<div class="demo-button-style">
@ -19,6 +28,7 @@
v-for="city in cities"
:key="city"
:label="city"
:value="city"
:disabled="city === 'Beijing'"
>{{ city }}</el-checkbox-button
>
@ -26,9 +36,13 @@
</div>
<div class="demo-button-style">
<el-checkbox-group v-model="checkboxGroup4" size="small" disabled>
<el-checkbox-button v-for="city in cities" :key="city" :label="city">{{
city
}}</el-checkbox-button>
<el-checkbox-button
v-for="city in cities"
:key="city"
:label="city"
:value="city"
>{{ city }}</el-checkbox-button
>
</el-checkbox-group>
</div>
</template>

View File

@ -1,15 +1,19 @@
<template>
<el-checkbox-group v-model="checkList">
<el-checkbox label="Option A" />
<el-checkbox label="Option B" />
<el-checkbox label="Option C" />
<el-checkbox label="disabled" disabled />
<el-checkbox label="selected and disabled" disabled />
<el-checkbox label="Option A" value="Value A" />
<el-checkbox label="Option B" value="Value B" />
<el-checkbox label="Option C" value="Value C" />
<el-checkbox label="disabled" value="Value disabled" disabled />
<el-checkbox
label="selected and disabled"
value="Value selected and disabled"
disabled
/>
</el-checkbox-group>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const checkList = ref(['selected and disabled', 'Option A'])
const checkList = ref(['Value selected and disabled', 'Value A'])
</script>

View File

@ -9,9 +9,13 @@
v-model="checkedCities"
@change="handleCheckedCitiesChange"
>
<el-checkbox v-for="city in cities" :key="city" :label="city">{{
city
}}</el-checkbox>
<el-checkbox
v-for="city in cities"
:key="city"
:label="city"
:value="city"
>{{ city }}</el-checkbox
>
</el-checkbox-group>
</template>

View File

@ -1,8 +1,12 @@
<template>
<el-checkbox-group v-model="checkedCities" :min="1" :max="2">
<el-checkbox v-for="city in cities" :key="city" :label="city">{{
city
}}</el-checkbox>
<el-checkbox
v-for="city in cities"
:key="city"
:label="city"
:value="city"
>{{ city }}</el-checkbox
>
</el-checkbox-group>
</template>

View File

@ -9,14 +9,14 @@
</div>
<div class="mt-4">
<el-checkbox-group v-model="checkboxGroup1" size="small">
<el-checkbox label="Option1" border />
<el-checkbox label="Option2" border />
<el-checkbox label="Option1" value="Value1" border />
<el-checkbox label="Option2" value="Value2" border />
</el-checkbox-group>
</div>
<div class="mt-4">
<el-checkbox-group v-model="checkboxGroup1" size="small">
<el-checkbox label="Option1" border disabled />
<el-checkbox label="Option2" border disabled />
<el-checkbox label="Option1" value="Value1" border disabled />
<el-checkbox label="Option2" value="Value2" border disabled />
</el-checkbox-group>
</div>
</template>
@ -28,5 +28,5 @@ const checked1 = ref(true)
const checked2 = ref(false)
const checked3 = ref(false)
const checked4 = ref(true)
const checkboxGroup1 = ref(['Option1'])
const checkboxGroup1 = ref(['Value1'])
</script>

View File

@ -1,26 +1,26 @@
<template>
<div class="mb-2 flex items-center text-sm">
<el-radio-group v-model="radio1" class="ml-4">
<el-radio label="1" size="large">Option 1</el-radio>
<el-radio label="2" size="large">Option 2</el-radio>
<el-radio value="1" size="large">Option 1</el-radio>
<el-radio value="2" size="large">Option 2</el-radio>
</el-radio-group>
</div>
<div class="my-2 flex items-center text-sm">
<el-radio-group v-model="radio2" class="ml-4">
<el-radio label="1">Option 1</el-radio>
<el-radio label="2">Option 2</el-radio>
<el-radio value="1">Option 1</el-radio>
<el-radio value="2">Option 2</el-radio>
</el-radio-group>
</div>
<div class="my-4 flex items-center text-sm">
<el-radio-group v-model="radio3" class="ml-4">
<el-radio label="1" size="small">Option 1</el-radio>
<el-radio label="2" size="small">Option 2</el-radio>
<el-radio value="1" size="small">Option 1</el-radio>
<el-radio value="2" size="small">Option 2</el-radio>
</el-radio-group>
</div>
<div class="mb-2 flex items-center text-sm">
<el-radio-group v-model="radio3" disabled class="ml-4">
<el-radio label="1" size="small">Option 1</el-radio>
<el-radio label="2" size="small">Option 2</el-radio>
<el-radio value="1" size="small">Option 1</el-radio>
<el-radio value="2" size="small">Option 2</el-radio>
</el-radio-group>
</div>
</template>

View File

@ -1,26 +1,26 @@
<template>
<div>
<el-radio-group v-model="radio1" size="large">
<el-radio-button label="New York" />
<el-radio-button label="Washington" />
<el-radio-button label="Los Angeles" />
<el-radio-button label="Chicago" />
<el-radio-button label="New York" value="New York" />
<el-radio-button label="Washington" value="Washington" />
<el-radio-button label="Los Angeles" value="Los Angeles" />
<el-radio-button label="Chicago" value="Chicago" />
</el-radio-group>
</div>
<div style="margin-top: 20px">
<el-radio-group v-model="radio2">
<el-radio-button label="New York" />
<el-radio-button label="Washington" />
<el-radio-button label="Los Angeles" />
<el-radio-button label="Chicago" />
<el-radio-button label="New York" value="New York" />
<el-radio-button label="Washington" value="Washington" />
<el-radio-button label="Los Angeles" value="Los Angeles" />
<el-radio-button label="Chicago" value="Chicago" />
</el-radio-group>
</div>
<div style="margin-top: 20px">
<el-radio-group v-model="radio3" size="small">
<el-radio-button label="New York" />
<el-radio-button label="Washington" disabled />
<el-radio-button label="Los Angeles" />
<el-radio-button label="Chicago" />
<el-radio-button label="New York" value="New York" />
<el-radio-button label="Washington" value="Washington" disabled />
<el-radio-button label="Los Angeles" value="Los Angeles" />
<el-radio-button label="Chicago" value="Chicago" />
</el-radio-group>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<el-radio v-model="radio" disabled label="disabled">Option A</el-radio>
<el-radio v-model="radio" disabled label="selected and disabled"
<el-radio v-model="radio" disabled value="disabled">Option A</el-radio>
<el-radio v-model="radio" disabled value="selected and disabled"
>Option B</el-radio
>
</template>

View File

@ -1,8 +1,8 @@
<template>
<el-radio-group v-model="radio">
<el-radio :label="3">Option A</el-radio>
<el-radio :label="6">Option B</el-radio>
<el-radio :label="9">Option C</el-radio>
<el-radio :value="3">Option A</el-radio>
<el-radio :value="6">Option B</el-radio>
<el-radio :value="9">Option C</el-radio>
</el-radio-group>
</template>

View File

@ -1,26 +1,26 @@
<template>
<div>
<el-radio-group v-model="radio1">
<el-radio label="1" size="large" border>Option A</el-radio>
<el-radio label="2" size="large" border>Option B</el-radio>
<el-radio value="1" size="large" border>Option A</el-radio>
<el-radio value="2" size="large" border>Option B</el-radio>
</el-radio-group>
</div>
<div style="margin-top: 20px">
<el-radio-group v-model="radio2">
<el-radio label="1" border>Option A</el-radio>
<el-radio label="2" border>Option B</el-radio>
<el-radio value="1" border>Option A</el-radio>
<el-radio value="2" border>Option B</el-radio>
</el-radio-group>
</div>
<div style="margin-top: 20px">
<el-radio-group v-model="radio3" size="small">
<el-radio label="1" border>Option A</el-radio>
<el-radio label="2" border disabled>Option B</el-radio>
<el-radio value="1" border>Option A</el-radio>
<el-radio value="2" border disabled>Option B</el-radio>
</el-radio-group>
</div>
<div style="margin-top: 20px">
<el-radio-group v-model="radio4" size="small" disabled>
<el-radio label="1" border>Option A</el-radio>
<el-radio label="2" border>Option B</el-radio>
<el-radio value="1" border>Option A</el-radio>
<el-radio value="2" border>Option B</el-radio>
</el-radio-group>
</div>
</template>

View File

@ -141,10 +141,10 @@ describe('Checkbox', () => {
setup() {
return () => (
<CheckboxGroup v-model={checkList.value}>
<Checkbox label="a" ref="a" />
<Checkbox label="b" ref="b" />
<Checkbox label="c" ref="c" />
<Checkbox label="d" ref="d" />
<Checkbox label="a" value="a" ref="a" />
<Checkbox label="b" value="b" ref="b" />
<Checkbox label="c" value="c" ref="c" />
<Checkbox label="d" value="d" ref="d" />
</CheckboxGroup>
)
},
@ -168,10 +168,10 @@ describe('Checkbox', () => {
setup() {
return () => (
<CheckboxGroup v-model={checkList.value}>
<Checkbox label="a" ref="a" />
<Checkbox label="b" ref="b" />
<Checkbox label="c" ref="c" />
<Checkbox label="d" ref="d" />
<Checkbox label="a" value="a" ref="a" />
<Checkbox label="b" value="b" ref="b" />
<Checkbox label="c" value="c" ref="c" />
<Checkbox label="d" value="d" ref="d" />
</CheckboxGroup>
)
},
@ -190,8 +190,8 @@ describe('Checkbox', () => {
setup() {
return () => (
<CheckboxGroup v-model={checkList.value} onChange={onChange}>
<Checkbox label="a" ref="a" />
<Checkbox label="b" ref="b" />
<Checkbox label="a" value="a" ref="a" />
<Checkbox label="b" value="b" ref="b" />
</CheckboxGroup>
)
},
@ -209,10 +209,10 @@ describe('Checkbox', () => {
setup() {
return () => (
<CheckboxGroup v-model={checkList.value}>
<Checkbox label="a" ref="a" />
<Checkbox label="b" ref="b" />
<Checkbox label="c" ref="c" />
<Checkbox label="d" ref="d" />
<Checkbox label="a" value="a" ref="a" />
<Checkbox label="b" value="b" ref="b" />
<Checkbox label="c" value="c" ref="c" />
<Checkbox label="d" value="d" ref="d" />
</CheckboxGroup>
)
},
@ -228,7 +228,7 @@ describe('Checkbox', () => {
const checked = ref('a')
const wrapper = mount(() => (
<ElFormItem label="test">
<Checkbox true-label="a" false-label={3} v-model={checked.value} />
<Checkbox true-value="a" false-value={3} v-model={checked.value} />
</ElFormItem>
))
@ -246,8 +246,8 @@ describe('Checkbox', () => {
const wrapper = mount(() => (
<Checkbox
label="Foobar"
true-label="a"
false-label={3}
true-value="a"
false-value={3}
v-model={checked.value}
/>
))
@ -263,7 +263,7 @@ describe('Checkbox', () => {
test('with label as slot content', async () => {
const checked = ref('a')
const wrapper = mount(() => (
<Checkbox true-label="a" false-label={3} v-model={checked.value}>
<Checkbox true-value="a" false-value={3} v-model={checked.value}>
Foobar
</Checkbox>
))
@ -284,7 +284,7 @@ describe('Checkbox', () => {
<div>
<Checkbox v-model={checked.value} checked />
<CheckboxGroup v-model={checklist.value}>
<Checkbox checked label="a" />
<Checkbox checked label="a" value="a" />
</CheckboxGroup>
</div>
))
@ -297,9 +297,15 @@ describe('Checkbox', () => {
const checklist = ref([])
const wrapper = mount(() => (
<CheckboxGroup v-model={checklist.value}>
<Checkbox label="">all</Checkbox>
<Checkbox label="a">a</Checkbox>
<Checkbox label="b">b</Checkbox>
<Checkbox label="" value="">
all
</Checkbox>
<Checkbox label="a" value="a">
a
</Checkbox>
<Checkbox label="b" value="b">
b
</Checkbox>
</CheckboxGroup>
))
@ -308,13 +314,13 @@ describe('Checkbox', () => {
expect(checklist.value[0]).toEqual('')
})
test('label is object', async () => {
test('value is object', async () => {
const checklist = ref([])
const wrapper = mount(() => (
<CheckboxGroup v-model={checklist.value}>
<Checkbox label={{ a: 1 }}>all</Checkbox>
<Checkbox label={{ a: 2 }}>a</Checkbox>
<Checkbox label={{ b: 1 }}>b</Checkbox>
<Checkbox value={{ a: 1 }}>all</Checkbox>
<Checkbox value={{ a: 2 }}>a</Checkbox>
<Checkbox value={{ b: 1 }}>b</Checkbox>
</CheckboxGroup>
))
@ -323,19 +329,19 @@ describe('Checkbox', () => {
expect(checklist.value[0]).toEqual({ a: 1 })
expect(checkbox.classes()).contains('is-checked')
})
test('label is object with initial values', async () => {
test('value is object with initial values', async () => {
const checklist = ref([{ a: 1 }])
const wrapper = mount({
setup() {
return () => (
<CheckboxGroup v-model={checklist.value}>
<Checkbox label={{ a: 1 }} ref="a1">
<Checkbox value={{ a: 1 }} ref="a1">
a1
</Checkbox>
<Checkbox label={{ a: 2 }} ref="a2">
<Checkbox value={{ a: 2 }} ref="a2">
a2
</Checkbox>
<Checkbox label={{ b: 1 }} ref="b1">
<Checkbox value={{ b: 1 }} ref="b1">
b1
</Checkbox>
</CheckboxGroup>
@ -400,10 +406,10 @@ describe('check-button', () => {
setup() {
return () => (
<CheckboxGroup v-model={checkList.value} onChange={onChange}>
<CheckboxButton label="a" ref="a" />
<CheckboxButton label="b" ref="b" />
<CheckboxButton label="c" ref="c" />
<CheckboxButton label="d" ref="d" />
<CheckboxButton label="a" value="a" ref="a" />
<CheckboxButton label="b" value="b" ref="b" />
<CheckboxButton label="c" value="c" ref="c" />
<CheckboxButton label="d" value="d" ref="d" />
</CheckboxGroup>
)
},
@ -426,10 +432,10 @@ describe('check-button', () => {
fill="#ff0000"
text-color="#000"
>
<CheckboxButton label="a" ref="a" />
<CheckboxButton label="b" ref="b" />
<CheckboxButton label="c" ref="c" />
<CheckboxButton label="d" ref="d" />
<CheckboxButton label="a" value="a" ref="a" />
<CheckboxButton label="b" value="b" ref="b" />
<CheckboxButton label="c" value="c" ref="c" />
<CheckboxButton label="d" value="d" ref="d" />
</CheckboxGroup>
)
},
@ -447,10 +453,10 @@ describe('check-button', () => {
const checkList = ref(['a', 'b'])
const wrapper = mount(() => (
<CheckboxGroup v-model={checkList.value} tag="tr">
<CheckboxButton label="a" ref="a" />
<CheckboxButton label="b" ref="b" />
<CheckboxButton label="c" ref="c" />
<CheckboxButton label="d" ref="d" />
<CheckboxButton label="a" value="a" ref="a" />
<CheckboxButton label="b" value="b" ref="b" />
<CheckboxButton label="c" value="c" ref="c" />
<CheckboxButton label="d" value="d" ref="d" />
</CheckboxGroup>
))
@ -463,11 +469,11 @@ describe('check-button', () => {
setup() {
return () => (
<CheckboxGroup v-model={checkList.value} min={2} max={3}>
<CheckboxButton label="a" ref="a" />
<CheckboxButton label="b" ref="b" />
<CheckboxButton label="c" ref="c" />
<CheckboxButton label="d" ref="d" />
<CheckboxButton label="e" ref="e" />
<CheckboxButton label="a" value="a" ref="a" />
<CheckboxButton label="b" value="b" ref="b" />
<CheckboxButton label="c" value="c" ref="c" />
<CheckboxButton label="d" value="d" ref="d" />
<CheckboxButton label="e" value="e" ref="e" />
</CheckboxGroup>
)
},
@ -529,10 +535,10 @@ describe('check-button', () => {
setup() {
return () => (
<CheckboxGroup v-model={checkList.value}>
<CheckboxButton label="a" ref="a" />
<CheckboxButton label="b" ref="b" />
<CheckboxButton label="c" ref="c" />
<CheckboxButton label="d" ref="d" />
<CheckboxButton label="a" value="a" ref="a" />
<CheckboxButton label="b" value="b" ref="b" />
<CheckboxButton label="c" value="c" ref="c" />
<CheckboxButton label="d" value="d" ref="d" />
</CheckboxGroup>
)
},
@ -551,7 +557,7 @@ describe('check-button', () => {
<div>
<Checkbox v-model={checked.value} checked />
<CheckboxGroup v-model={checklist.value}>
<CheckboxButton checked label="a" />
<CheckboxButton checked label="a" value="a" />
</CheckboxGroup>
</div>
))
@ -587,7 +593,7 @@ describe('check-button', () => {
test('checkbox with label, form item is group', async () => {
const wrapper = mount(() => (
<ElFormItem label="test">
<Checkbox label="Foo" />
<Checkbox label="Foo" value="Foo" />
</ElFormItem>
))
@ -604,8 +610,8 @@ describe('check-button', () => {
const wrapper = mount(() => (
<ElFormItem label="test">
<CheckboxGroup>
<Checkbox label="Foo" />
<Checkbox label="Bar" />
<Checkbox label="Foo" value="Foo" />
<Checkbox label="Bar" value="Bar" />
</CheckboxGroup>
</ElFormItem>
))
@ -627,8 +633,8 @@ describe('check-button', () => {
const wrapper = mount(() => (
<ElFormItem label="test">
<CheckboxGroup label="Foo">
<Checkbox label="Foo" />
<Checkbox label="Bar" />
<Checkbox label="Foo" value="Foo" />
<Checkbox label="Bar" value="Bar" />
</CheckboxGroup>
</ElFormItem>
))
@ -650,12 +656,12 @@ describe('check-button', () => {
return () => (
<ElFormItem label="test">
<CheckboxGroup label="Foo" ref="checkboxGroup1">
<Checkbox label="Foo" />
<Checkbox label="Bar" />
<Checkbox label="Foo" value="Foo" />
<Checkbox label="Bar" value="Bar" />
</CheckboxGroup>
<CheckboxGroup label="Bar" ref="checkboxGroup2">
<Checkbox label="Foo" />
<Checkbox label="Bar" />
<Checkbox label="Foo" value="Foo" />
<Checkbox label="Bar" value="Bar" />
</CheckboxGroup>
</ElFormItem>
)

View File

@ -1,15 +1,15 @@
<template>
<label :class="labelKls">
<input
v-if="trueLabel || falseLabel"
v-if="trueValue || falseValue || trueLabel || falseLabel"
v-model="model"
:class="ns.be('button', 'original')"
type="checkbox"
:name="name"
:tabindex="tabindex"
:disabled="isDisabled"
:true-value="trueLabel"
:false-value="falseLabel"
:true-value="trueValue || trueLabel"
:false-value="falseValue || falseLabel"
@change="handleChange"
@focus="isFocused = true"
@blur="isFocused = false"
@ -23,7 +23,7 @@
:name="name"
:tabindex="tabindex"
:disabled="isDisabled"
:value="label"
:value="actualValue"
@change="handleChange"
@focus="isFocused = true"
@blur="isFocused = false"
@ -63,6 +63,7 @@ const {
isDisabled,
checkboxButtonSize,
model,
actualValue,
handleChange,
} = useCheckbox(props, slots)
const checkboxGroup = inject(checkboxGroupContextKey, undefined)

View File

@ -16,12 +16,19 @@ export const checkboxProps = {
default: undefined,
},
/**
* @description value of the Checkbox when used inside a `checkbox-group`
* @description label of the Checkbox when used inside a `checkbox-group`
*/
label: {
type: [String, Boolean, Number, Object],
default: undefined,
},
/**
* @description value of the Checkbox when used inside a `checkbox-group`
*/
value: {
type: [String, Boolean, Number, Object],
default: undefined,
},
/**
* @description Set indeterminate state, only responsible for style control
*/
@ -44,11 +51,27 @@ export const checkboxProps = {
/**
* @description value of the Checkbox if it's checked
*/
trueValue: {
type: [String, Number],
default: undefined,
},
/**
* @description value of the Checkbox if it's not checked
*/
falseValue: {
type: [String, Number],
default: undefined,
},
/**
* @deprecated use `trueValue` instead
* @description value of the Checkbox if it's checked
*/
trueLabel: {
type: [String, Number],
default: undefined,
},
/**
* @deprecated use `falseValue` instead
* @description value of the Checkbox if it's not checked
*/
falseLabel: {

View File

@ -7,7 +7,7 @@
>
<span :class="spanKls">
<input
v-if="trueLabel || falseLabel"
v-if="trueValue || falseValue || trueLabel || falseLabel"
:id="inputId"
v-model="model"
:class="ns.e('original')"
@ -16,8 +16,8 @@
:name="name"
:tabindex="tabindex"
:disabled="isDisabled"
:true-value="trueLabel"
:false-value="falseLabel"
:true-value="trueValue || trueLabel"
:false-value="falseValue || falseLabel"
@change="handleChange"
@focus="isFocused = true"
@blur="isFocused = false"
@ -31,7 +31,7 @@
type="checkbox"
:indeterminate="indeterminate"
:disabled="isDisabled"
:value="label"
:value="actualValue"
:name="name"
:tabindex="tabindex"
@change="handleChange"
@ -71,6 +71,7 @@ const {
checkboxSize,
hasOwnLabel,
model,
actualValue,
handleChange,
onClickRoot,
} = useCheckbox(props, slots)

View File

@ -29,9 +29,9 @@ export const useCheckboxEvent = (
const { emit } = getCurrentInstance()!
function getLabeledValue(value: string | number | boolean) {
return value === props.trueLabel || value === true
? props.trueLabel ?? true
: props.falseLabel ?? false
return [true, props.trueValue, props.trueLabel].includes(value)
? (props.trueValue || props.trueLabel) ?? true
: (props.falseValue || props.falseLabel) ?? false
}
function emitChangeEvent(
@ -59,7 +59,7 @@ export const useCheckboxEvent = (
)
if (!hasLabel) {
model.value = getLabeledValue(
[false, props.falseLabel].includes(model.value)
[false, props.falseValue, props.falseLabel].includes(model.value)
)
await nextTick()
emitChangeEvent(model.value, e)

View File

@ -1,7 +1,7 @@
import { computed, inject, ref, toRaw } from 'vue'
import { isEqual, isNil } from 'lodash-unified'
import { isEqual } from 'lodash-unified'
import { useFormSize } from '@element-plus/components/form'
import { isArray, isBoolean, isObject } from '@element-plus/utils'
import { isArray, isBoolean, isObject, isPropAbsent } from '@element-plus/utils'
import { checkboxGroupContextKey } from '../constants'
import type { ComponentInternalInstance } from 'vue'
@ -15,18 +15,26 @@ export const useCheckboxStatus = (
) => {
const checkboxGroup = inject(checkboxGroupContextKey, undefined)
const isFocused = ref(false)
const actualValue = computed(() => {
// In version 2.x, if there's no props.value, props.label will act as props.value
// In version 3.x, remove this computed value, use props.value instead.
if (!isPropAbsent(props.value)) {
return props.value
}
return props.label
})
const isChecked = computed<boolean>(() => {
const value = model.value
if (isBoolean(value)) {
return value
} else if (isArray(value)) {
if (isObject(props.label)) {
return value.map(toRaw).some((o) => isEqual(o, props.label))
if (isObject(actualValue.value)) {
return value.map(toRaw).some((o) => isEqual(o, actualValue.value))
} else {
return value.map(toRaw).includes(props.label)
return value.map(toRaw).includes(actualValue.value)
}
} else if (value !== null && value !== undefined) {
return value === props.trueLabel
return value === props.trueValue || value === props.trueLabel
} else {
return !!value
}
@ -41,7 +49,7 @@ export const useCheckboxStatus = (
const checkboxSize = useFormSize(computed(() => checkboxGroup?.size?.value))
const hasOwnLabel = computed<boolean>(() => {
return !!slots.default || !isNil(props.label)
return !!slots.default || !isPropAbsent(actualValue.value)
})
return {
@ -50,6 +58,7 @@ export const useCheckboxStatus = (
isFocused,
checkboxSize,
hasOwnLabel,
actualValue,
}
}

View File

@ -1,27 +1,14 @@
import { computed } from 'vue'
import { useFormItem, useFormItemInputId } from '@element-plus/components/form'
import { isArray } from '@element-plus/utils'
import { isArray, isPropAbsent } from '@element-plus/utils'
import { useDeprecated } from '@element-plus/hooks'
import { useCheckboxDisabled } from './use-checkbox-disabled'
import { useCheckboxEvent } from './use-checkbox-event'
import { useCheckboxModel } from './use-checkbox-model'
import { useCheckboxStatus } from './use-checkbox-status'
import type { ComponentInternalInstance } from 'vue'
import type { CheckboxProps } from '../checkbox'
import type { CheckboxModel } from './use-checkbox-model'
const setStoreValue = (
props: CheckboxProps,
{ model }: Pick<CheckboxModel, 'model'>
) => {
function addToStore() {
if (isArray(model.value) && !model.value.includes(props.label)) {
model.value.push(props.label)
} else {
model.value = props.trueLabel || true
}
}
props.checked && addToStore()
}
import type { CheckboxProps } from '../checkbox'
export const useCheckbox = (
props: CheckboxProps,
@ -35,6 +22,7 @@ export const useCheckbox = (
checkboxButtonSize,
checkboxSize,
hasOwnLabel,
actualValue,
} = useCheckboxStatus(props, slots, { model })
const { isDisabled } = useCheckboxDisabled({ model, isChecked })
const { inputId, isLabeledByFormItem } = useFormItemInputId(props, {
@ -50,7 +38,51 @@ export const useCheckbox = (
isLabeledByFormItem,
})
setStoreValue(props, { model })
const setStoreValue = () => {
function addToStore() {
if (isArray(model.value) && !model.value.includes(actualValue.value)) {
model.value.push(actualValue.value)
} else {
model.value = props.trueValue || props.trueLabel || true
}
}
props.checked && addToStore()
}
setStoreValue()
useDeprecated(
{
from: 'label act as value',
replacement: 'value',
version: '3.0.0',
scope: 'el-checkbox',
ref: 'https://element-plus.org/en-US/component/checkbox.html',
},
computed(() => isGroup.value && isPropAbsent(props.value))
)
useDeprecated(
{
from: 'true-label',
replacement: 'true-value',
version: '3.0.0',
scope: 'el-checkbox',
ref: 'https://element-plus.org/en-US/component/checkbox.html',
},
computed(() => !!props.trueLabel)
)
useDeprecated(
{
from: 'false-label',
replacement: 'false-value',
version: '3.0.0',
scope: 'el-checkbox',
ref: 'https://element-plus.org/en-US/component/checkbox.html',
},
computed(() => !!props.falseLabel)
)
return {
inputId,
@ -62,6 +94,7 @@ export const useCheckbox = (
checkboxSize,
hasOwnLabel,
model,
actualValue,
handleChange,
onClickRoot,
}

View File

@ -70,13 +70,13 @@ describe('Radio group', () => {
const radio = ref(3)
const wrapper = mount(() => (
<RadioGroup v-model={radio.value}>
<Radio label={3} ref="radio1">
<Radio value={3} ref="radio1">
3
</Radio>
<Radio label={6} ref="radio2">
<Radio value={6} ref="radio2">
6
</Radio>
<Radio label={9}>9</Radio>
<Radio value={9}>9</Radio>
</RadioGroup>
))
await nextTick()
@ -91,26 +91,26 @@ describe('Radio group', () => {
const radioValue1 = ref(3)
const wrapper1 = mount(() => (
<RadioGroup v-model={radioValue1.value}>
<Radio label={3} ref="radio1">
<Radio value={3} ref="radio1">
3
</Radio>
<Radio label={6} ref="radio2">
<Radio value={6} ref="radio2">
6
</Radio>
<Radio label={9}>9</Radio>
<Radio value={9}>9</Radio>
</RadioGroup>
))
const radioValue2 = ref(3)
const wrapper2 = mount(() => (
<RadioGroup v-model={radioValue2.value}>
<Radio label={3} ref="radio1">
<Radio value={3} ref="radio1">
3
</Radio>
<Radio label={6} ref="radio2">
<Radio value={6} ref="radio2">
6
</Radio>
<Radio label={9}>9</Radio>
<Radio value={9}>9</Radio>
</RadioGroup>
))
@ -124,13 +124,13 @@ describe('Radio group', () => {
const radio = ref(3)
const wrapper = mount(() => (
<RadioGroup v-model={radio.value} disabled>
<Radio label={3} ref="radio1">
<Radio value={3} ref="radio1">
3
</Radio>
<Radio label={6} ref="radio2">
<Radio value={6} ref="radio2">
6
</Radio>
<Radio label={9}>9</Radio>
<Radio value={9}>9</Radio>
</RadioGroup>
))
expect(wrapper.find('label.is-disabled').exists()).toBe(true)
@ -149,11 +149,11 @@ describe('Radio group', () => {
}
const wrapper = mount(() => (
<RadioGroup v-model={radio.value} onChange={onChange}>
<Radio label={3}>3</Radio>
<Radio label={6} ref="radio2">
<Radio value={3}>3</Radio>
<Radio value={6} ref="radio2">
6
</Radio>
<Radio label={9}>9</Radio>
<Radio value={9}>9</Radio>
</RadioGroup>
))
const radio2 = wrapper.findAll('.el-radio').at(1)
@ -169,11 +169,11 @@ describe('Radio group', () => {
}
mount(() => (
<RadioGroup v-model={radio.value} onChange={onChange}>
<Radio label={3}>3</Radio>
<Radio label={6} ref="radio2">
<Radio value={3}>3</Radio>
<Radio value={6} ref="radio2">
6
</Radio>
<Radio label={9}>9</Radio>
<Radio value={9}>9</Radio>
</RadioGroup>
))
@ -185,13 +185,13 @@ describe('Radio group', () => {
const radio = ref(3)
const wrapper = mount(() => (
<RadioGroup v-model={radio.value} disabled>
<RadioButton label={3} ref="radio1">
<RadioButton value={3} ref="radio1">
3
</RadioButton>
<RadioButton label={6} ref="radio2">
<RadioButton value={6} ref="radio2">
6
</RadioButton>
<RadioButton label={9}>9</RadioButton>
<RadioButton value={9}>9</RadioButton>
</RadioGroup>
))
@ -209,13 +209,13 @@ describe('Radio Button', () => {
const radio = ref(3)
const wrapper = mount(() => (
<RadioGroup v-model={radio.value}>
<RadioButton label={3} ref="radio1">
<RadioButton value={3} ref="radio1">
3
</RadioButton>
<RadioButton label={6} ref="radio2">
<RadioButton value={6} ref="radio2">
6
</RadioButton>
<RadioButton label={9}>9</RadioButton>
<RadioButton value={9}>9</RadioButton>
</RadioGroup>
))
const [radio1, radio2] = wrapper.findAll('.el-radio-button')
@ -228,13 +228,13 @@ describe('Radio Button', () => {
const radio = ref(3)
const wrapper = mount(() => (
<RadioGroup v-model={radio.value} fill="#000" text-color="#ff0">
<RadioButton label={3} ref="radio1">
<RadioButton value={3} ref="radio1">
3
</RadioButton>
<RadioButton label={6} ref="radio2">
<RadioButton value={6} ref="radio2">
6
</RadioButton>
<RadioButton label={9}>9</RadioButton>
<RadioButton value={9}>9</RadioButton>
</RadioGroup>
))
const radio1 = wrapper.find('.el-radio-button')
@ -250,13 +250,13 @@ describe('Radio Button', () => {
}
const wrapper = mount(() => (
<RadioGroup v-model={radio.value} onChange={onChange}>
<RadioButton label={3} ref="radio1">
<RadioButton value={3} ref="radio1">
3
</RadioButton>
<RadioButton label={6} ref="radio2">
<RadioButton value={6} ref="radio2">
6
</RadioButton>
<RadioButton label={9}>9</RadioButton>
<RadioButton value={9}>9</RadioButton>
</RadioGroup>
))
const radio2 = wrapper.findAll('.el-radio-button').at(1)
@ -271,13 +271,13 @@ describe('Radio Button', () => {
}
mount(() => (
<RadioGroup v-model={radio.value} onChange={onChange}>
<RadioButton label={3} ref="radio1">
<RadioButton value={3} ref="radio1">
3
</RadioButton>
<RadioButton label={6} ref="radio2">
<RadioButton value={6} ref="radio2">
6
</RadioButton>
<RadioButton label={9}>9</RadioButton>
<RadioButton value={9}>9</RadioButton>
</RadioGroup>
))
@ -290,13 +290,13 @@ describe('Radio Button', () => {
const radio = ref(3)
const wrapper = mount(() => (
<RadioGroup v-model={radio.value} size="large">
<RadioButton label={3} ref="radio1">
<RadioButton value={3} ref="radio1">
3
</RadioButton>
<RadioButton label={6} ref="radio2">
<RadioButton value={6} ref="radio2">
6
</RadioButton>
<RadioButton label={9}>9</RadioButton>
<RadioButton value={9}>9</RadioButton>
</RadioGroup>
))
expect(wrapper.findAll('.el-radio-button--large').length).toBe(3)
@ -307,8 +307,8 @@ describe('Radio Button', () => {
const wrapper = mount(() => (
<ElFormItem ref="item" label="Test">
<RadioGroup ref="radioGroup">
<Radio label="Foo" />
<Radio label="Bar" />
<Radio label="Foo" value="Foo" />
<Radio label="Bar" value="Bar" />
</RadioGroup>
</ElFormItem>
))
@ -328,8 +328,8 @@ describe('Radio Button', () => {
const wrapper = mount(() => (
<ElFormItem ref="item" label="Test">
<RadioGroup label="Foo" ref="radioGroup">
<Radio label="Foo" />
<Radio label="Bar" />
<Radio label="Foo" value="Foo" />
<Radio label="Bar" value="Bar" />
</RadioGroup>
</ElFormItem>
))
@ -347,12 +347,12 @@ describe('Radio Button', () => {
const wrapper = mount(() => (
<ElFormItem ref="item" label="Test">
<RadioGroup label="Foo" ref="radioGroup1">
<Radio label="Foo" />
<Radio label="Bar" />
<Radio label="Foo" value="Foo" />
<Radio label="Bar" value="Bar" />
</RadioGroup>
<RadioGroup label="Bar" ref="radioGroup2">
<Radio label="Foo" />
<Radio label="Bar" />
<Radio label="Foo" value="Foo" />
<Radio label="Bar" value="Bar" />
</RadioGroup>
</ElFormItem>
))

View File

@ -5,13 +5,6 @@ import type RadioButton from './radio-button.vue'
export const radioButtonProps = buildProps({
...radioPropsBase,
/**
* @description native 'name' attribute
*/
name: {
type: String,
default: '',
},
} as const)
export type RadioButtonProps = ExtractPropTypes<typeof radioButtonProps>

View File

@ -2,7 +2,7 @@
<label
:class="[
ns.b('button'),
ns.is('active', modelValue === label),
ns.is('active', modelValue === actualValue),
ns.is('disabled', disabled),
ns.is('focus', focus),
ns.bm('button', size),
@ -12,7 +12,7 @@
ref="radioRef"
v-model="modelValue"
:class="ns.be('button', 'original-radio')"
:value="label"
:value="actualValue"
type="radio"
:name="name || radioGroup?.name"
:disabled="disabled"
@ -22,7 +22,7 @@
/>
<span
:class="ns.be('button', 'inner')"
:style="modelValue === label ? activeStyle : {}"
:style="modelValue === actualValue ? activeStyle : {}"
@keydown.stop
>
<slot>
@ -46,7 +46,7 @@ defineOptions({
const props = defineProps(radioButtonProps)
const ns = useNamespace('radio')
const { radioRef, focus, size, disabled, modelValue, radioGroup } =
const { radioRef, focus, size, disabled, modelValue, radioGroup, actualValue } =
useRadio(props)
const activeStyle = computed<CSSProperties>(() => {

View File

@ -25,7 +25,7 @@ export const radioGroupProps = buildProps({
*/
modelValue: {
type: [String, Number, Boolean],
default: '',
default: undefined,
},
/**
* @description border and background color when button is active

View File

@ -5,6 +5,13 @@ import type { ExtractPropTypes } from 'vue'
import type Radio from './radio.vue'
export const radioPropsBase = buildProps({
/**
* @description binding value
*/
modelValue: {
type: [String, Number, Boolean],
default: undefined,
},
/**
* @description size of the Radio
*/
@ -14,30 +21,30 @@ export const radioPropsBase = buildProps({
*/
disabled: Boolean,
/**
* @description the value of Radio
* @description the label of Radio
*/
label: {
type: [String, Number, Boolean],
default: '',
default: undefined,
},
})
export const radioProps = buildProps({
...radioPropsBase,
/**
* @description binding value
* @description the value of Radio
*/
modelValue: {
value: {
type: [String, Number, Boolean],
default: '',
default: undefined,
},
/**
* @description native `name` attribute
*/
name: {
type: String,
default: '',
default: undefined,
},
})
export const radioProps = buildProps({
...radioPropsBase,
/**
* @description whether to add a border around Radio
*/
@ -45,9 +52,9 @@ export const radioProps = buildProps({
} as const)
export const radioEmits = {
[UPDATE_MODEL_EVENT]: (val: string | number | boolean) =>
[UPDATE_MODEL_EVENT]: (val: string | number | boolean | undefined) =>
isString(val) || isNumber(val) || isBoolean(val),
[CHANGE_EVENT]: (val: string | number | boolean) =>
[CHANGE_EVENT]: (val: string | number | boolean | undefined) =>
isString(val) || isNumber(val) || isBoolean(val),
}

View File

@ -5,7 +5,7 @@
ns.is('disabled', disabled),
ns.is('focus', focus),
ns.is('bordered', border),
ns.is('checked', modelValue === label),
ns.is('checked', modelValue === actualValue),
ns.m(size),
]"
>
@ -13,14 +13,14 @@
:class="[
ns.e('input'),
ns.is('disabled', disabled),
ns.is('checked', modelValue === label),
ns.is('checked', modelValue === actualValue),
]"
>
<input
ref="radioRef"
v-model="modelValue"
:class="ns.e('original')"
:value="label"
:value="actualValue"
:name="name || radioGroup?.name"
:disabled="disabled"
type="radio"
@ -53,10 +53,8 @@ const props = defineProps(radioProps)
const emit = defineEmits(radioEmits)
const ns = useNamespace('radio')
const { radioRef, radioGroup, focus, size, disabled, modelValue } = useRadio(
props,
emit
)
const { radioRef, radioGroup, focus, size, disabled, modelValue, actualValue } =
useRadio(props, emit)
function handleChange() {
nextTick(() => emit('change', modelValue.value))

View File

@ -1,18 +1,28 @@
import { computed, inject, ref } from 'vue'
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { useFormDisabled, useFormSize } from '@element-plus/components/form'
import { useDeprecated } from '@element-plus/hooks'
import { isPropAbsent } from '@element-plus/utils'
import { radioGroupKey } from './constants'
import type { RadioButtonProps } from './radio-button'
import type { SetupContext } from 'vue'
import type { RadioEmits, RadioProps } from './radio'
export const useRadio = (
props: { label: RadioProps['label']; modelValue?: RadioProps['modelValue'] },
props: RadioProps | RadioButtonProps,
emit?: SetupContext<RadioEmits>['emit']
) => {
const radioRef = ref<HTMLInputElement>()
const radioGroup = inject(radioGroupKey, undefined)
const isGroup = computed(() => !!radioGroup)
const actualValue = computed(() => {
// In version 2.x, if there's no props.value, props.label will act as props.value
// In version 3.x, remove this computed value, use props.value instead.
if (!isPropAbsent(props.value)) {
return props.value
}
return props.label
})
const modelValue = computed<RadioProps['modelValue']>({
get() {
return isGroup.value ? radioGroup!.modelValue : props.modelValue!
@ -23,7 +33,7 @@ export const useRadio = (
} else {
emit && emit(UPDATE_MODEL_EVENT, val)
}
radioRef.value!.checked = props.modelValue === props.label
radioRef.value!.checked = props.modelValue === actualValue.value
},
})
@ -31,11 +41,23 @@ export const useRadio = (
const disabled = useFormDisabled(computed(() => radioGroup?.disabled))
const focus = ref(false)
const tabIndex = computed(() => {
return disabled.value || (isGroup.value && modelValue.value !== props.label)
return disabled.value ||
(isGroup.value && modelValue.value !== actualValue.value)
? -1
: 0
})
useDeprecated(
{
from: 'label act as value',
replacement: 'value',
version: '3.0.0',
scope: 'el-radio',
ref: 'https://element-plus.org/en-US/component/radio.html',
},
computed(() => isGroup.value && isPropAbsent(props.value))
)
return {
radioRef,
isGroup,
@ -45,5 +67,6 @@ export const useRadio = (
disabled,
tabIndex,
modelValue,
actualValue,
}
}