import { provide, nextTick, defineComponent, ref, watch } from 'vue'; import type { PropType, ExtractPropTypes } from 'vue'; import classNames from '../_util/classNames'; import PropTypes from '../_util/vue-types'; import Radio from './Radio'; import useConfigInject from '../_util/hooks/useConfigInject'; import { tuple } from '../_util/type'; import type { RadioChangeEvent, RadioGroupButtonStyle, RadioGroupOptionType } from './interface'; import { useInjectFormItemContext } from '../form/FormItemContext'; const RadioGroupSizeTypes = tuple('large', 'default', 'small'); export type RadioGroupSize = typeof RadioGroupSizeTypes[number]; export type RadioGroupOption = RadioGroupOptionType; export type RadioGroupChildOption = { label?: any; value: any; disabled?: boolean; }; export const radioGroupProps = () => ({ prefixCls: String, value: PropTypes.any, size: PropTypes.oneOf(RadioGroupSizeTypes).def('default'), options: { type: Array as PropType>, }, disabled: { type: Boolean, default: undefined }, name: String, buttonStyle: { type: String as PropType, default: 'outline' }, id: String, optionType: { type: String as PropType, default: 'default' }, onChange: Function as PropType<(e: RadioChangeEvent) => void>, 'onUpdate:value': Function as PropType<(val: any) => void>, }); export type RadioGroupProps = Partial>>; export default defineComponent({ name: 'ARadioGroup', props: radioGroupProps(), // emits: ['update:value', 'change'], setup(props, { slots, emit }) { const formItemContext = useInjectFormItemContext(); const { prefixCls, direction, size } = useConfigInject('radio', props); const stateValue = ref(props.value); const updatingValue = ref(false); watch( () => props.value, val => { stateValue.value = val; updatingValue.value = false; }, ); const onRadioChange = (ev: RadioChangeEvent) => { const lastValue = stateValue.value; const { value } = ev.target; if (!('value' in props)) { stateValue.value = value; } // nextTick for https://github.com/vueComponent/ant-design-vue/issues/1280 if (!updatingValue.value && value !== lastValue) { updatingValue.value = true; emit('update:value', value); emit('change', ev); formItemContext.onFieldChange(); } nextTick(() => { updatingValue.value = false; }); }; provide('radioGroupContext', { onRadioChange, stateValue, props, }); return () => { const { options, optionType, buttonStyle, id = formItemContext.id.value } = props; const groupPrefixCls = `${prefixCls.value}-group`; const classString = classNames(groupPrefixCls, `${groupPrefixCls}-${buttonStyle}`, { [`${groupPrefixCls}-${size.value}`]: size.value, [`${groupPrefixCls}-rtl`]: direction.value === 'rtl', }); let children = null; if (options && options.length > 0) { const optionsPrefixCls = optionType === 'button' ? `${prefixCls.value}-button` : prefixCls.value; children = options.map(option => { if (typeof option === 'string' || typeof option === 'number') { return ( {option} ); } const { value, disabled, label } = option as RadioGroupChildOption; return ( {label} ); }); } else { children = slots.default?.(); } return (
{children}
); }; }, });