Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(components): [radio] switch to script-setup synatx #7701

Merged
merged 3 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('Radio', () => {
expect(wrapper.classes()).toContain('is-bordered')
})

test('disabled', async () => {
test('change event', async () => {
const wrapper = _mount(
`<el-radio
v-model="radio"
Expand Down
2 changes: 2 additions & 0 deletions packages/components/radio/src/radio-button.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { buildProps } from '@element-plus/utils'
import { radioPropsBase } from './radio'
import type { ExtractPropTypes } from 'vue'
import type RadioButton from './radio-button.vue'

export const radioButtonProps = buildProps({
...radioPropsBase,
Expand All @@ -11,3 +12,4 @@ export const radioButtonProps = buildProps({
} as const)

export type RadioButtonProps = ExtractPropTypes<typeof radioButtonProps>
export type RadioButtonInstance = InstanceType<typeof RadioButton>
53 changes: 16 additions & 37 deletions packages/components/radio/src/radio-button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,51 +30,30 @@
</span>
</label>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'

<script lang="ts" setup>
import { computed } from 'vue'
import { useNamespace } from '@element-plus/hooks'
import { useRadio } from './radio'
import { radioButtonProps } from './radio-button'
import type { CSSProperties } from 'vue'

export default defineComponent({
defineOptions({
name: 'ElRadioButton',
props: radioButtonProps,
})

setup(props, { emit }) {
const ns = useNamespace('radio')
const {
radioRef,
isGroup,
focus,
size,
disabled,
tabIndex,
modelValue,
radioGroup,
} = useRadio(props, emit)
const props = defineProps(radioButtonProps)

const activeStyle = computed<CSSProperties>(() => {
return {
backgroundColor: radioGroup?.fill || '',
borderColor: radioGroup?.fill || '',
boxShadow: radioGroup?.fill ? `-1px 0 0 0 ${radioGroup.fill}` : '',
color: radioGroup?.textColor || '',
}
})
const ns = useNamespace('radio')
const { radioRef, focus, size, disabled, modelValue, radioGroup } =
useRadio(props)

return {
ns,
isGroup,
size,
disabled,
tabIndex,
modelValue,
focus,
activeStyle,
radioRef,
radioGroup,
}
},
const activeStyle = computed<CSSProperties>(() => {
return {
backgroundColor: radioGroup?.fill || '',
borderColor: radioGroup?.fill || '',
boxShadow: radioGroup?.fill ? `-1px 0 0 0 ${radioGroup.fill}` : '',
color: radioGroup?.textColor || '',
}
})
</script>
2 changes: 2 additions & 0 deletions packages/components/radio/src/radio-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { buildProps } from '@element-plus/utils'
import { useSizeProp } from '@element-plus/hooks'
import { radioEmits } from './radio'
import type { ExtractPropTypes } from '@vue/runtime-core'
import type RadioGroup from './radio-group.vue'

export const radioGroupProps = buildProps({
id: {
Expand Down Expand Up @@ -35,3 +36,4 @@ export type RadioGroupProps = ExtractPropTypes<typeof radioGroupProps>

export const radioGroupEmits = radioEmits
export type RadioGroupEmits = typeof radioGroupEmits
export type RadioGroupInstance = InstanceType<typeof RadioGroup>
102 changes: 36 additions & 66 deletions packages/components/radio/src/radio-group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,14 @@
:class="ns.b('group')"
role="radiogroup"
:aria-label="!isLabeledByFormItem ? label || 'radio-group' : undefined"
:aria-labelledby="isLabeledByFormItem ? formItem.labelId : undefined"
:aria-labelledby="isLabeledByFormItem ? formItem!.labelId : undefined"
>
<slot />
</div>
</template>

<script lang="ts">
import {
computed,
defineComponent,
nextTick,
onMounted,
provide,
reactive,
ref,
toRefs,
watch,
} from 'vue'
<script lang="ts" setup>
import { nextTick, onMounted, provide, reactive, ref, toRefs, watch } from 'vue'
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { radioGroupKey } from '@element-plus/tokens'
import {
Expand All @@ -34,64 +24,44 @@ import { debugWarn } from '@element-plus/utils'
import { radioGroupEmits, radioGroupProps } from './radio-group'
import type { RadioGroupProps } from '..'

let id = 1
export default defineComponent({
defineOptions({
name: 'ElRadioGroup',
props: radioGroupProps,
emits: radioGroupEmits,

setup(props, ctx) {
const ns = useNamespace('radio')
const radioGroupRef = ref<HTMLDivElement>()
const { formItem } = useFormItem()
const { inputId: groupId, isLabeledByFormItem } = useFormItemInputId(
props,
{
formItemContext: formItem,
}
)

const changeEvent = (value: RadioGroupProps['modelValue']) => {
ctx.emit(UPDATE_MODEL_EVENT, value)
nextTick(() => ctx.emit('change', value))
}
})

onMounted(() => {
const radios =
radioGroupRef.value!.querySelectorAll<HTMLInputElement>('[type=radio]')
const firstLabel = radios[0]
if (!Array.from(radios).some((radio) => radio.checked) && firstLabel) {
firstLabel.tabIndex = 0
}
})
const props = defineProps(radioGroupProps)
const emit = defineEmits(radioGroupEmits)

const randomName = `el-radio-group-${id++}`
const ns = useNamespace('radio')
const radioGroupRef = ref<HTMLDivElement>()
const { formItem } = useFormItem()
const { inputId: groupId, isLabeledByFormItem } = useFormItemInputId(props, {
formItemContext: formItem,
})

const name = computed(() => {
return props.name || randomName
})
const changeEvent = (value: RadioGroupProps['modelValue']) => {
emit(UPDATE_MODEL_EVENT, value)
nextTick(() => emit('change', value))
}

provide(
radioGroupKey,
reactive({
...toRefs(props),
changeEvent,
name,
})
)
onMounted(() => {
const radios =
radioGroupRef.value!.querySelectorAll<HTMLInputElement>('[type=radio]')
const firstLabel = radios[0]
if (!Array.from(radios).some((radio) => radio.checked) && firstLabel) {
firstLabel.tabIndex = 0
}
})

watch(
() => props.modelValue,
() => formItem?.validate('change').catch((err) => debugWarn(err))
)
provide(
radioGroupKey,
reactive({
...toRefs(props),
changeEvent,
})
)

return {
ns,
radioGroupRef,
formItem,
groupId,
isLabeledByFormItem,
}
},
})
watch(
() => props.modelValue,
() => formItem?.validate('change').catch((err) => debugWarn(err))
)
</script>
12 changes: 8 additions & 4 deletions packages/components/radio/src/radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { radioGroupKey } from '@element-plus/tokens'
import { useDisabled, useSize, useSizeProp } from '@element-plus/hooks'
import type { ExtractPropTypes, SetupContext } from 'vue'
import type Radio from './radio.vue'

export const radioPropsBase = buildProps({
size: useSizeProp,
Expand All @@ -13,6 +14,7 @@ export const radioPropsBase = buildProps({
default: '',
},
})

export const radioProps = buildProps({
...radioPropsBase,
modelValue: {
Expand All @@ -25,19 +27,17 @@ export const radioProps = buildProps({
},
border: Boolean,
} as const)
export type RadioProps = ExtractPropTypes<typeof radioProps>

export const radioEmits = {
[UPDATE_MODEL_EVENT]: (val: string | number | boolean) =>
isString(val) || isNumber(val) || isBoolean(val),
change: (val: string | number | boolean) =>
isString(val) || isNumber(val) || isBoolean(val),
}
export type RadioEmits = typeof radioEmits

export const useRadio = (
props: { label: RadioProps['label']; modelValue?: RadioProps['modelValue'] },
emit: SetupContext<RadioEmits>['emit']
emit?: SetupContext<RadioEmits>['emit']
) => {
const radioRef = ref<HTMLInputElement>()
const radioGroup = inject(radioGroupKey, undefined)
Expand All @@ -50,7 +50,7 @@ export const useRadio = (
if (isGroup.value) {
radioGroup!.changeEvent(val)
} else {
emit(UPDATE_MODEL_EVENT, val)
emit && emit(UPDATE_MODEL_EVENT, val)
}
radioRef.value!.checked = props.modelValue === props.label
},
Expand All @@ -76,3 +76,7 @@ export const useRadio = (
modelValue,
}
}

export type RadioProps = ExtractPropTypes<typeof radioProps>
export type RadioEmits = typeof radioEmits
export type RadioInstance = InstanceType<typeof Radio>
49 changes: 14 additions & 35 deletions packages/components/radio/src/radio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,46 +38,25 @@
</label>
</template>

<script lang="ts">
import { defineComponent, nextTick } from 'vue'
<script lang="ts" setup>
import { nextTick } from 'vue'
import { useNamespace } from '@element-plus/hooks'
import { radioEmits, radioProps, useRadio } from './radio'

export default defineComponent({
defineOptions({
name: 'ElRadio',
props: radioProps,
emits: radioEmits,

setup(props, { emit }) {
const ns = useNamespace('radio')
const {
radioRef,
isGroup,
radioGroup,
focus,
size,
disabled,
tabIndex,
modelValue,
} = useRadio(props, emit)
})

function handleChange() {
nextTick(() => emit('change', modelValue.value))
}
const props = defineProps(radioProps)
const emit = defineEmits(radioEmits)

return {
ns,
focus,
isGroup,
radioGroup,
modelValue,
tabIndex,
size,
disabled,
radioRef,
const ns = useNamespace('radio')
const { radioRef, radioGroup, focus, size, disabled, modelValue } = useRadio(
props,
emit
)

handleChange,
}
},
})
function handleChange() {
nextTick(() => emit('change', modelValue.value))
}
</script>