diff --git a/docs/en-US/component/rate.md b/docs/en-US/component/rate.md
index 9bedab804c..a051515a9c 100644
--- a/docs/en-US/component/rate.md
+++ b/docs/en-US/component/rate.md
@@ -41,6 +41,14 @@ rate/text
:::
+## Clearable
+
+:::demo You can reset the value to `0` when you click at the same value again.
+
+rate/clearable
+
+:::
+
## More icons
You can use different icons to distinguish different rate components.
@@ -97,6 +105,7 @@ Use `css/scss` language to change the global or local color. We set some global
| text-color | color of texts | string | — | #1F2D3D |
| texts | text array | array | — | ['Extremely bad', 'Disappointed', 'Fair', 'Satisfied', 'Surprise'] |
| score-template | score template | string | — | {value} |
+| clearable | whether value can be reset to `0` | boolean | — | false |
## Events
diff --git a/docs/examples/rate/clearable.vue b/docs/examples/rate/clearable.vue
new file mode 100644
index 0000000000..08129bf3a1
--- /dev/null
+++ b/docs/examples/rate/clearable.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/packages/components/rate/__tests__/rate.test.tsx b/packages/components/rate/__tests__/rate.test.tsx
index b9aeb0ce45..8d04ac75a6 100644
--- a/packages/components/rate/__tests__/rate.test.tsx
+++ b/packages/components/rate/__tests__/rate.test.tsx
@@ -113,6 +113,29 @@ describe('Rate.vue', () => {
expect(changeCount.value).toEqual(1)
})
+ it('clearable', () => {
+ const value = ref(4)
+ const changeCount = ref(0)
+ const handleChange = () => {
+ changeCount.value++
+ }
+ const wrapper = mount(() => (
+
+ ))
+
+ const fourthStar = wrapper.findAll('.el-rate__item')[3]
+ .element as HTMLElement
+ fourthStar.click()
+
+ expect(value.value).toEqual(0)
+ expect(changeCount.value).toEqual(1)
+ const fifthStar = wrapper.findAll('.el-rate__item')[4]
+ .element as HTMLElement
+ fifthStar.click()
+ expect(value.value).toEqual(5)
+ expect(changeCount.value).toEqual(2)
+ })
+
describe('form item accessibility integration', () => {
it('automatic id attachment', async () => {
const wrapper = mount(() => (
diff --git a/packages/components/rate/src/rate.ts b/packages/components/rate/src/rate.ts
index b2d9da8e5d..e010ce08e2 100644
--- a/packages/components/rate/src/rate.ts
+++ b/packages/components/rate/src/rate.ts
@@ -98,6 +98,10 @@ export const rateProps = buildProps({
type: String,
default: undefined,
},
+ clearable: {
+ type: Boolean,
+ default: false,
+ },
} as const)
export type RateProps = ExtractPropTypes
diff --git a/packages/components/rate/src/rate.vue b/packages/components/rate/src/rate.vue
index 52dc14a12c..2bea9b2d69 100644
--- a/packages/components/rate/src/rate.vue
+++ b/packages/components/rate/src/rate.vue
@@ -195,20 +195,26 @@ function showDecimalIcon(item: number) {
return showWhenDisabled || showWhenAllowHalf
}
+function emitValue(value: number) {
+ // if allow clear, and selected value is same as modelValue, reset value to 0
+ if (props.clearable && value === props.modelValue) {
+ value = 0
+ }
+
+ emit(UPDATE_MODEL_EVENT, value)
+ if (props.modelValue !== value) {
+ emit('change', value)
+ }
+}
+
function selectValue(value: number) {
if (rateDisabled.value) {
return
}
if (props.allowHalf && pointerAtLeftHalf.value) {
- emit(UPDATE_MODEL_EVENT, currentValue.value)
- if (props.modelValue !== currentValue.value) {
- emit('change', currentValue.value)
- }
+ emitValue(currentValue.value)
} else {
- emit(UPDATE_MODEL_EVENT, value)
- if (props.modelValue !== value) {
- emit('change', value)
- }
+ emitValue(value)
}
}