diff --git a/components/slider/index.tsx b/components/slider/index.tsx
index 8350c9d50..613a139f2 100644
--- a/components/slider/index.tsx
+++ b/components/slider/index.tsx
@@ -10,6 +10,7 @@ import type { TooltipPlacement } from '../tooltip/Tooltip';
import useConfigInject from '../_util/hooks/useConfigInject';
import SliderTooltip from './SliderTooltip';
import classNames from '../_util/classNames';
+import { useInjectFormItemContext } from '../form/FormItemContext';
export type SliderValue = number | [number, number];
@@ -39,6 +40,7 @@ type Value = [number, number] | number;
const defaultTipFormatter = (value: number) => (typeof value === 'number' ? value.toString() : '');
export const sliderProps = () => ({
+ id: String,
prefixCls: String,
tooltipPrefixCls: String,
range: { type: [Boolean, Object] as PropType
, default: undefined },
@@ -78,11 +80,12 @@ const Slider = defineComponent({
props: {
...sliderProps(),
},
- emits: ['update:value', 'change', 'afterChange'],
+ emits: ['update:value', 'change', 'afterChange', 'blur'],
slots: ['mark'],
setup(props, { attrs, slots, emit, expose }) {
const { prefixCls, rootPrefixCls, direction, getPopupContainer, configProvider } =
useConfigInject('slider', props);
+ const formItemContext = useInjectFormItemContext();
const sliderRef = ref();
const visibles = ref({});
const toggleTooltipVisible = (index: number, visible: boolean) => {
@@ -107,6 +110,10 @@ const Slider = defineComponent({
const handleChange = (val: SliderValue) => {
emit('update:value', val);
emit('change', val);
+ formItemContext.onFieldChange();
+ };
+ const handleBlur = () => {
+ emit('blur');
};
expose({
focus,
@@ -140,7 +147,12 @@ const Slider = defineComponent({
);
};
return () => {
- const { tooltipPrefixCls: customizeTooltipPrefixCls, range, ...restProps } = props;
+ const {
+ tooltipPrefixCls: customizeTooltipPrefixCls,
+ range,
+ id = formItemContext.id.value,
+ ...restProps
+ } = props;
const tooltipPrefixCls = configProvider.getPrefixCls('tooltip', customizeTooltipPrefixCls);
const cls = classNames(attrs.class, {
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
@@ -181,6 +193,7 @@ const Slider = defineComponent({
return (
);
diff --git a/components/switch/index.tsx b/components/switch/index.tsx
index 719ef670e..47333d4bb 100644
--- a/components/switch/index.tsx
+++ b/components/switch/index.tsx
@@ -9,10 +9,12 @@ import { tuple, withInstall } from '../_util/type';
import { getPropsSlot } from '../_util/props-util';
import Omit from 'omit.js';
import useConfigInject from '../_util/hooks/useConfigInject';
+import { useInjectFormItemContext } from '../form/FormItemContext';
export const SwitchSizes = tuple('small', 'default');
type CheckedType = boolean | string | number;
const switchProps = {
+ id: PropTypes.string,
prefixCls: PropTypes.string,
size: PropTypes.oneOf(SwitchSizes),
disabled: PropTypes.looseBool,
@@ -55,8 +57,9 @@ const Switch = defineComponent({
inheritAttrs: false,
props: switchProps,
slots: ['checkedChildren', 'unCheckedChildren'],
- emits: ['update:checked', 'mouseup', 'change', 'click', 'keydown'],
+ emits: ['update:checked', 'mouseup', 'change', 'click', 'keydown', 'blur'],
setup(props, { attrs, slots, expose, emit }) {
+ const formItemContext = useInjectFormItemContext();
onBeforeMount(() => {
warning(
!('defaultChecked' in attrs),
@@ -104,6 +107,11 @@ const Switch = defineComponent({
}
emit('update:checked', check);
emit('change', check, e);
+ formItemContext.onFieldChange();
+ };
+
+ const handleBlur = () => {
+ emit('blur');
};
const handleClick = (e: MouseEvent) => {
@@ -147,10 +155,13 @@ const Switch = defineComponent({
'defaultChecked',
'checkedValue',
'unCheckedValue',
+ 'id',
])}
{...attrs}
+ id={props.id ?? formItemContext.id.value}
onKeydown={handleKeyDown}
onClick={handleClick}
+ onBlur={handleBlur}
onMouseup={handleMouseUp}
type="button"
role="switch"
diff --git a/components/time-picker/time-picker.tsx b/components/time-picker/time-picker.tsx
index 309950ff8..ddafac133 100644
--- a/components/time-picker/time-picker.tsx
+++ b/components/time-picker/time-picker.tsx
@@ -11,6 +11,7 @@ import type { GenerateConfig } from '../vc-picker/generate';
import type { PanelMode, RangeValue } from '../vc-picker/interface';
import type { RangePickerSharedProps } from '../vc-picker/RangePicker';
import devWarning from '../vc-util/devWarning';
+import { useInjectFormItemContext } from '../form/FormItemContext';
export interface TimePickerLocale {
placeholder?: string;
@@ -74,6 +75,7 @@ function createTimePicker<
slot: ['addon', 'renderExtraFooter', 'suffixIcon', 'clearIcon'],
emits: ['change', 'openChange', 'focus', 'blur', 'ok', 'update:value', 'update:open'],
setup(props, { slots, expose, emit, attrs }) {
+ const formItemContext = useInjectFormItemContext();
devWarning(
!(slots.addon || props.addon),
'TimePicker',
@@ -91,6 +93,7 @@ function createTimePicker<
const onChange = (value: DateType | string, dateString: string) => {
emit('update:value', value);
emit('change', value, dateString);
+ formItemContext.onFieldChange();
};
const onOpenChange = (open: boolean) => {
emit('update:open', open);
@@ -101,15 +104,18 @@ function createTimePicker<
};
const onBlur = () => {
emit('blur');
+ formItemContext.onFieldBlur();
};
const onOk = (value: DateType) => {
emit('ok', value);
};
return () => {
+ const { id = formItemContext.id.value, ...restProps } = props;
return (
{
pickerRef.value?.focus();
@@ -166,6 +175,7 @@ function createTimePicker<
) => {
emit('update:value', values);
emit('change', values, dateStrings);
+ formItemContext.onFieldChange();
};
const onOpenChange = (open: boolean) => {
emit('update:open', open);
@@ -176,6 +186,7 @@ function createTimePicker<
};
const onBlur = () => {
emit('blur');
+ formItemContext.onFieldBlur();
};
const onPanelChange = (
values: RangeValue | RangeValue,
@@ -194,10 +205,12 @@ function createTimePicker<
emit('calendarChange', values, dateStrings, info);
};
return () => {
+ const { id = formItemContext.id.value, ...restProps } = props;
return (
, default: [] },
disabled: { type: Boolean, default: undefined },
@@ -118,6 +120,7 @@ const Transfer = defineComponent({
const sourceSelectedKeys = ref([]);
const targetSelectedKeys = ref([]);
+ const formItemContext = useInjectFormItemContext();
watch(
() => props.selectedKeys,
() => {
@@ -164,6 +167,7 @@ const Transfer = defineComponent({
emit('update:targetKeys', newTargetKeys);
handleSelectChange(oppositeDirection, []);
emit('change', newTargetKeys, direction, newMoveKeys);
+ formItemContext.onFieldChange();
};
const moveToLeft = () => {
@@ -312,6 +316,7 @@ const Transfer = defineComponent({
selectAllLabels = [],
oneWay,
pagination,
+ id = formItemContext.id.value,
} = props;
const { class: className, style } = attrs;
@@ -335,7 +340,7 @@ const Transfer = defineComponent({
const rightTitle =
(titles && titles[1]) ?? slots.rightTitle?.() ?? (locale.titles || ['', ''])[1];
return (
-
+
{
if (transitionName !== undefined) {
@@ -92,6 +93,8 @@ const TreeSelect = defineComponent({
'`replaceFields` is deprecated, please use fieldNames instead',
);
});
+
+ const formItemContext = useInjectFormItemContext();
const {
configProvider,
prefixCls,
@@ -131,6 +134,7 @@ const TreeSelect = defineComponent({
const handleChange = (...args: any[]) => {
emit('update:value', args[0]);
emit('change', ...args);
+ formItemContext.onFieldChange();
};
const handleTreeExpand = (...args: any[]) => {
emit('update:treeExpandedKeys', args[0]);
@@ -140,6 +144,10 @@ const TreeSelect = defineComponent({
emit('update:searchValue', args[0]);
emit('search', ...args);
};
+ const handleBlur = () => {
+ emit('blur');
+ formItemContext.onFieldBlur();
+ };
return () => {
const {
notFoundContent = slots.notFoundContent?.(),
@@ -154,6 +162,7 @@ const TreeSelect = defineComponent({
treeLine,
switcherIcon = slots.switcherIcon?.(),
fieldNames = props.replaceFields,
+ id = formItemContext.id.value,
} = props;
// ===================== Icons =====================
const { suffixIcon, removeIcon, clearIcon } = getIcons(
@@ -202,6 +211,7 @@ const TreeSelect = defineComponent({
virtual={virtual.value}
dropdownMatchSelectWidth={dropdownMatchSelectWidth.value}
{...selectProps}
+ id={id}
fieldNames={fieldNames}
ref={treeSelectRef}
prefixCls={prefixCls.value}
@@ -223,6 +233,7 @@ const TreeSelect = defineComponent({
choiceTransitionName={getTransitionName(rootPrefixCls, '', choiceTransitionName)}
transitionName={getTransitionName(rootPrefixCls, 'slide-up', transitionName)}
onChange={handleChange}
+ onBlur={handleBlur}
onSearch={handleSearch}
onTreeExpand={handleTreeExpand}
v-slots={{
diff --git a/components/upload/Upload.tsx b/components/upload/Upload.tsx
index e90a8a537..53f4c868a 100644
--- a/components/upload/Upload.tsx
+++ b/components/upload/Upload.tsx
@@ -14,6 +14,7 @@ import { UploadProps } from './interface';
import { T, fileToObject, genPercentAdd, getFileItem, removeFileItem } from './utils';
import { defineComponent, inject } from 'vue';
import { getDataAndAriaProps } from '../_util/util';
+import { useInjectFormItemContext } from '../form/FormItemContext';
export type UploadFileStatus = 'error' | 'success' | 'done' | 'uploading' | 'removed';
export interface UploadFile {
@@ -54,10 +55,12 @@ export default defineComponent({
supportServerRender: true,
}),
setup() {
+ const formItemContext = useInjectFormItemContext();
return {
upload: null,
progressTimer: null,
configProvider: inject('configProvider', defaultConfigProvider),
+ formItemContext,
};
},
// recentUploadStatus: boolean | PromiseLike;
@@ -190,6 +193,7 @@ export default defineComponent({
}
this.$emit('update:fileList', info.fileList);
this.$emit('change', info);
+ this.formItemContext.onFieldChange();
},
onFileDrop(e) {
this.setState({
@@ -276,6 +280,7 @@ export default defineComponent({
const vcUploadProps = {
...this.$props,
+ id: this.$props.id ?? this.formItemContext.id.value,
prefixCls,
beforeUpload: this.reBeforeUpload,
onStart: this.onStart,
diff --git a/components/vc-input-number/src/index.jsx b/components/vc-input-number/src/index.jsx
index 81899219e..a99ac56be 100755
--- a/components/vc-input-number/src/index.jsx
+++ b/components/vc-input-number/src/index.jsx
@@ -158,7 +158,6 @@ export default defineComponent({
typeof nextValue === 'number' &&
nextValue > max
) {
- this.__emit('update:value', max);
this.__emit('change', max);
}
if (
@@ -167,7 +166,6 @@ export default defineComponent({
typeof nextValue === 'number' &&
nextValue < min
) {
- this.__emit('update:value', min);
this.__emit('change', min);
}
}
@@ -277,7 +275,6 @@ export default defineComponent({
this.rawInput = this.parser(this.getValueFromEvent(e));
this.setState({ inputValue: this.rawInput });
const num = this.toNumber(this.rawInput); // valid number or invalid string
- this.__emit('update:value', num);
this.__emit('change', num);
},
onFocus(...args) {
@@ -374,7 +371,6 @@ export default defineComponent({
);
}
if (changed) {
- this.__emit('update:value', newValue);
this.__emit('change', newValue);
}
return newValue;
diff --git a/components/vc-slider/src/common/createSlider.tsx b/components/vc-slider/src/common/createSlider.tsx
index e12cbb234..aaf7b4d02 100644
--- a/components/vc-slider/src/common/createSlider.tsx
+++ b/components/vc-slider/src/common/createSlider.tsx
@@ -16,6 +16,7 @@ function noop() {}
export default function createSlider(Component) {
// const displayName = `ComponentEnhancer(${Component.displayName})`
const propTypes = {
+ id: PropTypes.string,
min: PropTypes.number,
max: PropTypes.number,
step: PropTypes.number,
@@ -292,8 +293,9 @@ export default function createSlider(Component) {
railStyle,
dotStyle,
activeDotStyle,
+ id,
} = this;
- const { class: className, style, id } = this.$attrs;
+ const { class: className, style } = this.$attrs;
const { tracks, handles } = this.renderSlider();
const sliderClassName = classNames(prefixCls, className, {