perf: update formItem
parent
c4a60d6070
commit
c487be05a8
|
@ -27,6 +27,7 @@ import { defaultConfigProvider } from '../config-provider';
|
||||||
import type { VueNode } from '../_util/type';
|
import type { VueNode } from '../_util/type';
|
||||||
import { tuple, withInstall } from '../_util/type';
|
import { tuple, withInstall } from '../_util/type';
|
||||||
import type { RenderEmptyHandler } from '../config-provider/renderEmpty';
|
import type { RenderEmptyHandler } from '../config-provider/renderEmpty';
|
||||||
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
|
|
||||||
export interface CascaderOptionType {
|
export interface CascaderOptionType {
|
||||||
value?: string | number;
|
value?: string | number;
|
||||||
|
@ -220,12 +221,14 @@ const Cascader = defineComponent({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: cascaderProps,
|
props: cascaderProps,
|
||||||
setup() {
|
setup() {
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
return {
|
return {
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
configProvider: inject('configProvider', defaultConfigProvider),
|
||||||
localeData: inject('localeData', {} as any),
|
localeData: inject('localeData', {} as any),
|
||||||
cachedOptions: [],
|
cachedOptions: [],
|
||||||
popupRef: undefined,
|
popupRef: undefined,
|
||||||
input: undefined,
|
input: undefined,
|
||||||
|
formItemContext,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -323,6 +326,7 @@ const Cascader = defineComponent({
|
||||||
inputFocused: false,
|
inputFocused: false,
|
||||||
});
|
});
|
||||||
this.$emit('blur', e);
|
this.$emit('blur', e);
|
||||||
|
this.formItemContext.onFieldBlur();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleInputClick(e: MouseEvent & { nativeEvent?: any }) {
|
handleInputClick(e: MouseEvent & { nativeEvent?: any }) {
|
||||||
|
@ -354,6 +358,7 @@ const Cascader = defineComponent({
|
||||||
}
|
}
|
||||||
this.$emit('update:value', value);
|
this.$emit('update:value', value);
|
||||||
this.$emit('change', value, selectedOptions);
|
this.$emit('change', value, selectedOptions);
|
||||||
|
this.formItemContext.onFieldChange();
|
||||||
},
|
},
|
||||||
|
|
||||||
getLabel() {
|
getLabel() {
|
||||||
|
@ -474,7 +479,12 @@ const Cascader = defineComponent({
|
||||||
...otherProps
|
...otherProps
|
||||||
} = props as any;
|
} = props as any;
|
||||||
const { onEvents, extraAttrs } = splitAttrs(this.$attrs);
|
const { onEvents, extraAttrs } = splitAttrs(this.$attrs);
|
||||||
const { class: className, style, ...restAttrs } = extraAttrs;
|
const {
|
||||||
|
class: className,
|
||||||
|
style,
|
||||||
|
id = this.formItemContext.id.value,
|
||||||
|
...restAttrs
|
||||||
|
} = extraAttrs;
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||||
const renderEmpty = this.configProvider.renderEmpty;
|
const renderEmpty = this.configProvider.renderEmpty;
|
||||||
const prefixCls = getPrefixCls('cascader', customizePrefixCls);
|
const prefixCls = getPrefixCls('cascader', customizePrefixCls);
|
||||||
|
@ -570,6 +580,7 @@ const Cascader = defineComponent({
|
||||||
const inputProps = {
|
const inputProps = {
|
||||||
...restAttrs,
|
...restAttrs,
|
||||||
...tempInputProps,
|
...tempInputProps,
|
||||||
|
id,
|
||||||
prefixCls: inputPrefixCls,
|
prefixCls: inputPrefixCls,
|
||||||
placeholder: value && value.length > 0 ? undefined : placeholder,
|
placeholder: value && value.length > 0 ? undefined : placeholder,
|
||||||
value: inputValue,
|
value: inputValue,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { defaultConfigProvider } from '../config-provider';
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
import type { RadioChangeEvent } from '../radio/interface';
|
import type { RadioChangeEvent } from '../radio/interface';
|
||||||
import type { EventHandler } from '../_util/EventInterface';
|
import type { EventHandler } from '../_util/EventInterface';
|
||||||
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
export const checkboxProps = () => {
|
export const checkboxProps = () => {
|
||||||
|
@ -38,7 +39,9 @@ export default defineComponent({
|
||||||
props: checkboxProps(),
|
props: checkboxProps(),
|
||||||
emits: ['change', 'update:checked'],
|
emits: ['change', 'update:checked'],
|
||||||
setup() {
|
setup() {
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
return {
|
return {
|
||||||
|
formItemContext,
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
configProvider: inject('configProvider', defaultConfigProvider),
|
||||||
checkboxGroupContext: inject('checkboxGroupContext', undefined),
|
checkboxGroupContext: inject('checkboxGroupContext', undefined),
|
||||||
};
|
};
|
||||||
|
@ -96,7 +99,13 @@ export default defineComponent({
|
||||||
const props = getOptionProps(this);
|
const props = getOptionProps(this);
|
||||||
const { checkboxGroupContext: checkboxGroup, $attrs } = this;
|
const { checkboxGroupContext: checkboxGroup, $attrs } = this;
|
||||||
const children = getSlot(this);
|
const children = getSlot(this);
|
||||||
const { indeterminate, prefixCls: customizePrefixCls, skipGroup, ...restProps } = props;
|
const {
|
||||||
|
indeterminate,
|
||||||
|
prefixCls: customizePrefixCls,
|
||||||
|
skipGroup,
|
||||||
|
id = this.formItemContext.id.value,
|
||||||
|
...restProps
|
||||||
|
} = props;
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||||
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
|
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
|
||||||
const {
|
const {
|
||||||
|
@ -109,12 +118,14 @@ export default defineComponent({
|
||||||
} = $attrs;
|
} = $attrs;
|
||||||
const checkboxProps: any = {
|
const checkboxProps: any = {
|
||||||
...restProps,
|
...restProps,
|
||||||
|
id,
|
||||||
prefixCls,
|
prefixCls,
|
||||||
...restAttrs,
|
...restAttrs,
|
||||||
};
|
};
|
||||||
if (checkboxGroup && !skipGroup) {
|
if (checkboxGroup && !skipGroup) {
|
||||||
checkboxProps.onChange = (...args) => {
|
checkboxProps.onChange = (...args) => {
|
||||||
this.$emit('change', ...args);
|
this.$emit('change', ...args);
|
||||||
|
this.formItemContext.onFieldChange();
|
||||||
checkboxGroup.toggleOption({ label: children, value: props.value });
|
checkboxGroup.toggleOption({ label: children, value: props.value });
|
||||||
};
|
};
|
||||||
checkboxProps.name = checkboxGroup.name;
|
checkboxProps.name = checkboxGroup.name;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Checkbox from './Checkbox';
|
||||||
import hasProp, { getSlot } from '../_util/props-util';
|
import hasProp, { getSlot } from '../_util/props-util';
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
import { defaultConfigProvider } from '../config-provider';
|
||||||
import type { VueNode } from '../_util/type';
|
import type { VueNode } from '../_util/type';
|
||||||
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
|
|
||||||
export type CheckboxValueType = string | number | boolean;
|
export type CheckboxValueType = string | number | boolean;
|
||||||
export interface CheckboxOptionType {
|
export interface CheckboxOptionType {
|
||||||
|
@ -25,10 +26,13 @@ export default defineComponent({
|
||||||
options: { type: Array as PropType<Array<CheckboxOptionType | string>> },
|
options: { type: Array as PropType<Array<CheckboxOptionType | string>> },
|
||||||
disabled: PropTypes.looseBool,
|
disabled: PropTypes.looseBool,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
|
id: PropTypes.string,
|
||||||
},
|
},
|
||||||
emits: ['change', 'update:value'],
|
emits: ['change', 'update:value'],
|
||||||
setup() {
|
setup() {
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
return {
|
return {
|
||||||
|
formItemContext,
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
configProvider: inject('configProvider', defaultConfigProvider),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -95,11 +99,12 @@ export default defineComponent({
|
||||||
// this.$emit('input', val);
|
// this.$emit('input', val);
|
||||||
this.$emit('update:value', val);
|
this.$emit('update:value', val);
|
||||||
this.$emit('change', val);
|
this.$emit('change', val);
|
||||||
|
this.formItemContext.onFieldChange();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
const { $props: props, $data: state } = this;
|
const { $props: props, $data: state } = this;
|
||||||
const { prefixCls: customizePrefixCls, options } = props;
|
const { prefixCls: customizePrefixCls, options, id = this.formItemContext.id.value } = props;
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||||
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
|
const prefixCls = getPrefixCls('checkbox', customizePrefixCls);
|
||||||
let children = getSlot(this);
|
let children = getSlot(this);
|
||||||
|
@ -120,6 +125,10 @@ export default defineComponent({
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return <div class={groupPrefixCls}>{children}</div>;
|
return (
|
||||||
|
<div class={groupPrefixCls} id={id}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { commonProps, rangePickerProps } from './props';
|
||||||
import type { PanelMode, RangeValue } from '../../vc-picker/interface';
|
import type { PanelMode, RangeValue } from '../../vc-picker/interface';
|
||||||
import type { RangePickerSharedProps } from '../../vc-picker/RangePicker';
|
import type { RangePickerSharedProps } from '../../vc-picker/RangePicker';
|
||||||
import devWarning from '../../vc-util/devWarning';
|
import devWarning from '../../vc-util/devWarning';
|
||||||
|
import { useInjectFormItemContext } from 'ant-design-vue/es/form/FormItemContext';
|
||||||
|
|
||||||
export default function generateRangePicker<DateType, ExtraProps = {}>(
|
export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
generateConfig: GenerateConfig<DateType>,
|
generateConfig: GenerateConfig<DateType>,
|
||||||
|
@ -52,6 +53,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
'blur',
|
'blur',
|
||||||
],
|
],
|
||||||
setup(props, { expose, slots, attrs, emit }) {
|
setup(props, { expose, slots, attrs, emit }) {
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
devWarning(
|
devWarning(
|
||||||
!attrs.getCalendarContainer,
|
!attrs.getCalendarContainer,
|
||||||
'DatePicker',
|
'DatePicker',
|
||||||
|
@ -86,6 +88,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
const values = maybeToStrings(dates);
|
const values = maybeToStrings(dates);
|
||||||
emit('update:value', values);
|
emit('update:value', values);
|
||||||
emit('change', values, dateStrings);
|
emit('change', values, dateStrings);
|
||||||
|
formItemContext.onFieldChange();
|
||||||
};
|
};
|
||||||
const onOpenChange = (open: boolean) => {
|
const onOpenChange = (open: boolean) => {
|
||||||
emit('update:open', open);
|
emit('update:open', open);
|
||||||
|
@ -96,6 +99,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
};
|
};
|
||||||
const onBlur = () => {
|
const onBlur = () => {
|
||||||
emit('blur');
|
emit('blur');
|
||||||
|
formItemContext.onFieldBlur();
|
||||||
};
|
};
|
||||||
const onPanelChange = (dates: RangeValue<DateType>, modes: [PanelMode, PanelMode]) => {
|
const onPanelChange = (dates: RangeValue<DateType>, modes: [PanelMode, PanelMode]) => {
|
||||||
const values = maybeToStrings(dates);
|
const values = maybeToStrings(dates);
|
||||||
|
@ -154,6 +158,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
renderExtraFooter = slots.renderExtraFooter,
|
renderExtraFooter = slots.renderExtraFooter,
|
||||||
separator = slots.separator?.(),
|
separator = slots.separator?.(),
|
||||||
clearIcon = slots.clearIcon?.(),
|
clearIcon = slots.clearIcon?.(),
|
||||||
|
id = formItemContext.id.value,
|
||||||
...restProps
|
...restProps
|
||||||
} = p;
|
} = p;
|
||||||
const { format, showTime } = p as any;
|
const { format, showTime } = p as any;
|
||||||
|
@ -187,6 +192,7 @@ export default function generateRangePicker<DateType, ExtraProps = {}>(
|
||||||
transitionName={transitionName || `${rootPrefixCls.value}-slide-up`}
|
transitionName={transitionName || `${rootPrefixCls.value}-slide-up`}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
{...additionalOverrideProps}
|
{...additionalOverrideProps}
|
||||||
|
id={id}
|
||||||
value={value.value}
|
value={value.value}
|
||||||
defaultValue={defaultValue.value}
|
defaultValue={defaultValue.value}
|
||||||
defaultPickerValue={defaultPickerValue.value}
|
defaultPickerValue={defaultPickerValue.value}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import classNames from '../../_util/classNames';
|
||||||
import { commonProps, datePickerProps } from './props';
|
import { commonProps, datePickerProps } from './props';
|
||||||
|
|
||||||
import devWarning from '../../vc-util/devWarning';
|
import devWarning from '../../vc-util/devWarning';
|
||||||
|
import { useInjectFormItemContext } from 'ant-design-vue/es/form/FormItemContext';
|
||||||
|
|
||||||
export default function generateSinglePicker<DateType, ExtraProps = {}>(
|
export default function generateSinglePicker<DateType, ExtraProps = {}>(
|
||||||
generateConfig: GenerateConfig<DateType>,
|
generateConfig: GenerateConfig<DateType>,
|
||||||
|
@ -51,6 +52,7 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
|
||||||
'update:open',
|
'update:open',
|
||||||
],
|
],
|
||||||
setup(props, { slots, expose, attrs, emit }) {
|
setup(props, { slots, expose, attrs, emit }) {
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
devWarning(
|
devWarning(
|
||||||
!(props.monthCellContentRender || slots.monthCellContentRender),
|
!(props.monthCellContentRender || slots.monthCellContentRender),
|
||||||
'DatePicker',
|
'DatePicker',
|
||||||
|
@ -91,6 +93,7 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
|
||||||
const value = maybeToString(date);
|
const value = maybeToString(date);
|
||||||
emit('update:value', value);
|
emit('update:value', value);
|
||||||
emit('change', value, dateString);
|
emit('change', value, dateString);
|
||||||
|
formItemContext.onFieldChange();
|
||||||
};
|
};
|
||||||
const onOpenChange = (open: boolean) => {
|
const onOpenChange = (open: boolean) => {
|
||||||
emit('update:open', open);
|
emit('update:open', open);
|
||||||
|
@ -101,6 +104,7 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
|
||||||
};
|
};
|
||||||
const onBlur = () => {
|
const onBlur = () => {
|
||||||
emit('blur');
|
emit('blur');
|
||||||
|
formItemContext.onFieldBlur();
|
||||||
};
|
};
|
||||||
const onPanelChange = (date: DateType, mode: PanelMode | null) => {
|
const onPanelChange = (date: DateType, mode: PanelMode | null) => {
|
||||||
const value = maybeToString(date);
|
const value = maybeToString(date);
|
||||||
|
@ -157,6 +161,7 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
|
||||||
(props as any).monthCellContentRender ||
|
(props as any).monthCellContentRender ||
|
||||||
slots.monthCellContentRender,
|
slots.monthCellContentRender,
|
||||||
clearIcon = slots.clearIcon?.(),
|
clearIcon = slots.clearIcon?.(),
|
||||||
|
id = formItemContext.id.value,
|
||||||
...restProps
|
...restProps
|
||||||
} = p;
|
} = p;
|
||||||
const showTime = p.showTime === '' ? true : p.showTime;
|
const showTime = p.showTime === '' ? true : p.showTime;
|
||||||
|
@ -198,6 +203,7 @@ export default function generateSinglePicker<DateType, ExtraProps = {}>(
|
||||||
transitionName={transitionName || `${rootPrefixCls.value}-slide-up`}
|
transitionName={transitionName || `${rootPrefixCls.value}-slide-up`}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
{...additionalOverrideProps}
|
{...additionalOverrideProps}
|
||||||
|
id={id}
|
||||||
picker={mergedPicker}
|
picker={mergedPicker}
|
||||||
value={value.value}
|
value={value.value}
|
||||||
defaultValue={defaultValue.value}
|
defaultValue={defaultValue.value}
|
||||||
|
|
|
@ -4,9 +4,8 @@ import cloneDeep from 'lodash-es/cloneDeep';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import Row from '../grid/Row';
|
import Row from '../grid/Row';
|
||||||
import type { ColProps } from '../grid/Col';
|
import type { ColProps } from '../grid/Col';
|
||||||
import { isValidElement, flattenChildren, filterEmpty } from '../_util/props-util';
|
import { filterEmpty } from '../_util/props-util';
|
||||||
import BaseMixin from '../_util/BaseMixin';
|
import BaseMixin from '../_util/BaseMixin';
|
||||||
import { cloneElement } from '../_util/vnode';
|
|
||||||
import { validateRules as validateRulesUtil } from './utils/validateUtil';
|
import { validateRules as validateRulesUtil } from './utils/validateUtil';
|
||||||
import { getNamePath } from './utils/valueUtil';
|
import { getNamePath } from './utils/valueUtil';
|
||||||
import { toArray } from './utils/typeUtil';
|
import { toArray } from './utils/typeUtil';
|
||||||
|
@ -19,6 +18,7 @@ import { useInjectForm } from './context';
|
||||||
import FormItemLabel from './FormItemLabel';
|
import FormItemLabel from './FormItemLabel';
|
||||||
import FormItemInput from './FormItemInput';
|
import FormItemInput from './FormItemInput';
|
||||||
import type { ValidationRule } from './Form';
|
import type { ValidationRule } from './Form';
|
||||||
|
import { useProvideFormItemContext } from './FormItemContext';
|
||||||
|
|
||||||
const ValidateStatuses = tuple('success', 'warning', 'error', 'validating', '');
|
const ValidateStatuses = tuple('success', 'warning', 'error', 'validating', '');
|
||||||
export type ValidateStatus = typeof ValidateStatuses[number];
|
export type ValidateStatus = typeof ValidateStatuses[number];
|
||||||
|
@ -271,6 +271,12 @@ export default defineComponent({
|
||||||
clearValidate,
|
clearValidate,
|
||||||
resetField,
|
resetField,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useProvideFormItemContext({
|
||||||
|
id: fieldId,
|
||||||
|
onFieldBlur,
|
||||||
|
onFieldChange,
|
||||||
|
});
|
||||||
let registered = false;
|
let registered = false;
|
||||||
watch(
|
watch(
|
||||||
fieldName,
|
fieldName,
|
||||||
|
@ -318,36 +324,36 @@ export default defineComponent({
|
||||||
}));
|
}));
|
||||||
return () => {
|
return () => {
|
||||||
const help = props.help ?? (slots.help ? filterEmpty(slots.help()) : null);
|
const help = props.help ?? (slots.help ? filterEmpty(slots.help()) : null);
|
||||||
const children = flattenChildren(slots.default?.());
|
// const children = flattenChildren(slots.default?.());
|
||||||
let firstChildren = children[0];
|
// let firstChildren = children[0];
|
||||||
if (fieldName.value && props.autoLink && isValidElement(firstChildren)) {
|
// if (fieldName.value && props.autoLink && isValidElement(firstChildren)) {
|
||||||
const originalEvents = firstChildren.props || {};
|
// const originalEvents = firstChildren.props || {};
|
||||||
const originalBlur = originalEvents.onBlur;
|
// const originalBlur = originalEvents.onBlur;
|
||||||
const originalChange = originalEvents.onChange;
|
// const originalChange = originalEvents.onChange;
|
||||||
firstChildren = cloneElement(firstChildren, {
|
// firstChildren = cloneElement(firstChildren, {
|
||||||
...(fieldId.value ? { id: fieldId.value } : undefined),
|
// ...(fieldId.value ? { id: fieldId.value } : undefined),
|
||||||
onBlur: (...args: any[]) => {
|
// onBlur: (...args: any[]) => {
|
||||||
if (Array.isArray(originalChange)) {
|
// if (Array.isArray(originalChange)) {
|
||||||
for (let i = 0, l = originalChange.length; i < l; i++) {
|
// for (let i = 0, l = originalChange.length; i < l; i++) {
|
||||||
originalBlur[i](...args);
|
// originalBlur[i](...args);
|
||||||
}
|
// }
|
||||||
} else if (originalBlur) {
|
// } else if (originalBlur) {
|
||||||
originalBlur(...args);
|
// originalBlur(...args);
|
||||||
}
|
// }
|
||||||
onFieldBlur();
|
// onFieldBlur();
|
||||||
},
|
// },
|
||||||
onChange: (...args: any[]) => {
|
// onChange: (...args: any[]) => {
|
||||||
if (Array.isArray(originalChange)) {
|
// if (Array.isArray(originalChange)) {
|
||||||
for (let i = 0, l = originalChange.length; i < l; i++) {
|
// for (let i = 0, l = originalChange.length; i < l; i++) {
|
||||||
originalChange[i](...args);
|
// originalChange[i](...args);
|
||||||
}
|
// }
|
||||||
} else if (originalChange) {
|
// } else if (originalChange) {
|
||||||
originalChange(...args);
|
// originalChange(...args);
|
||||||
}
|
// }
|
||||||
onFieldChange();
|
// onFieldChange();
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
return (
|
return (
|
||||||
<Row
|
<Row
|
||||||
{...attrs}
|
{...attrs}
|
||||||
|
@ -357,32 +363,37 @@ export default defineComponent({
|
||||||
attrs.class,
|
attrs.class,
|
||||||
]}
|
]}
|
||||||
key="row"
|
key="row"
|
||||||
>
|
v-slots={{
|
||||||
{/* Label */}
|
default: () => (
|
||||||
<FormItemLabel
|
<>
|
||||||
{...props}
|
{/* Label */}
|
||||||
htmlFor={fieldId.value}
|
<FormItemLabel
|
||||||
required={isRequired.value}
|
{...props}
|
||||||
requiredMark={formContext.requiredMark.value}
|
htmlFor={fieldId.value}
|
||||||
prefixCls={prefixCls.value}
|
required={isRequired.value}
|
||||||
onClick={onLabelClick}
|
requiredMark={formContext.requiredMark.value}
|
||||||
label={props.label ?? slots.label?.()}
|
prefixCls={prefixCls.value}
|
||||||
/>
|
onClick={onLabelClick}
|
||||||
{/* Input Group */}
|
label={props.label ?? slots.label?.()}
|
||||||
<FormItemInput
|
/>
|
||||||
{...props}
|
{/* Input Group */}
|
||||||
errors={help !== undefined && help !== null ? toArray(help) : errors.value}
|
<FormItemInput
|
||||||
prefixCls={prefixCls.value}
|
{...props}
|
||||||
status={validateState.value}
|
errors={help !== undefined && help !== null ? toArray(help) : errors.value}
|
||||||
onDomErrorVisibleChange={(v: boolean) => (domErrorVisible.value = v)}
|
prefixCls={prefixCls.value}
|
||||||
validateStatus={validateState.value}
|
status={validateState.value}
|
||||||
ref={inputRef}
|
onDomErrorVisibleChange={(v: boolean) => (domErrorVisible.value = v)}
|
||||||
help={help}
|
validateStatus={validateState.value}
|
||||||
extra={props.extra ?? slots.extra?.()}
|
ref={inputRef}
|
||||||
>
|
help={help}
|
||||||
{[firstChildren, children.slice(1)]}
|
extra={props.extra ?? slots.extra?.()}
|
||||||
</FormItemInput>
|
v-slots={{ default: slots.default }}
|
||||||
</Row>
|
// v-slots={{ default: () => [firstChildren, children.slice(1)] }}
|
||||||
|
></FormItemInput>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
></Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import type { ComputedRef, InjectionKey } from 'vue';
|
||||||
|
import { computed, inject, provide } from 'vue';
|
||||||
|
|
||||||
|
export type FormItemContext = {
|
||||||
|
id: ComputedRef<string | number>;
|
||||||
|
onFieldBlur: () => void;
|
||||||
|
onFieldChange: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ContextProps = FormItemContext;
|
||||||
|
|
||||||
|
const ContextKey: InjectionKey<ContextProps> = Symbol('ContextProps');
|
||||||
|
|
||||||
|
export const useProvideFormItemContext = (props: ContextProps) => {
|
||||||
|
provide(ContextKey, props);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useInjectFormItemContext = () => {
|
||||||
|
const defaultContext: ContextProps = {
|
||||||
|
id: computed(() => undefined),
|
||||||
|
onFieldBlur: () => {},
|
||||||
|
onFieldChange: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
// We should prevent the passing of context for children
|
||||||
|
|
||||||
|
provide(ContextKey, defaultContext);
|
||||||
|
return inject(ContextKey, defaultContext);
|
||||||
|
};
|
|
@ -86,33 +86,32 @@ const FormItemInput = defineComponent({
|
||||||
|
|
||||||
// Should provides additional icon if `hasFeedback`
|
// Should provides additional icon if `hasFeedback`
|
||||||
const IconNode = validateStatus && iconMap[validateStatus];
|
const IconNode = validateStatus && iconMap[validateStatus];
|
||||||
const icon =
|
|
||||||
hasFeedback && IconNode ? (
|
|
||||||
<span class={`${baseClassName}-children-icon`}>
|
|
||||||
<IconNode />
|
|
||||||
</span>
|
|
||||||
) : null;
|
|
||||||
|
|
||||||
const inputDom = (
|
|
||||||
<div class={`${baseClassName}-control-input`}>
|
|
||||||
<div class={`${baseClassName}-control-input-content`}>{slots.default?.()}</div>
|
|
||||||
{icon}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
const errorListDom = (
|
|
||||||
<ErrorList errors={errors} help={help} onDomErrorVisibleChange={onDomErrorVisibleChange} />
|
|
||||||
);
|
|
||||||
|
|
||||||
// If extra = 0, && will goes wrong
|
|
||||||
// 0&&error -> 0
|
|
||||||
const extraDom = extra ? <div class={`${baseClassName}-extra`}>{extra}</div> : null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col {...mergedWrapperCol} class={className}>
|
<Col
|
||||||
{inputDom}
|
{...mergedWrapperCol}
|
||||||
{errorListDom}
|
class={className}
|
||||||
{extraDom}
|
v-slots={{
|
||||||
</Col>
|
default: () => (
|
||||||
|
<>
|
||||||
|
<div class={`${baseClassName}-control-input`}>
|
||||||
|
<div class={`${baseClassName}-control-input-content`}>{slots.default?.()}</div>
|
||||||
|
{hasFeedback && IconNode ? (
|
||||||
|
<span class={`${baseClassName}-children-icon`}>
|
||||||
|
<IconNode />
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<ErrorList
|
||||||
|
errors={errors}
|
||||||
|
help={help}
|
||||||
|
onDomErrorVisibleChange={onDomErrorVisibleChange}
|
||||||
|
/>
|
||||||
|
{extra ? <div class={`${baseClassName}-extra`}>{extra}</div> : null}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
></Col>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,12 +27,13 @@ Just add the `rules` attribute for `Form` component, pass validation rules, and
|
||||||
<a-input v-model:value="formState.name" />
|
<a-input v-model:value="formState.name" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Activity zone" name="region">
|
<a-form-item label="Activity zone" name="region">
|
||||||
<a-select v-model:value="formState.region" placeholder="please select your zone">
|
<a-select
|
||||||
<a-select-option value="shanghai">Zone one</a-select-option>
|
v-model:value="formState.region"
|
||||||
<a-select-option value="beijing">Zone two</a-select-option>
|
placeholder="please select your zone"
|
||||||
</a-select>
|
:options="option"
|
||||||
|
></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Activity time" required name="date1">
|
<!-- <a-form-item label="Activity time" required name="date1">
|
||||||
<a-date-picker
|
<a-date-picker
|
||||||
v-model:value="formState.date1"
|
v-model:value="formState.date1"
|
||||||
show-time
|
show-time
|
||||||
|
@ -59,7 +60,7 @@ Just add the `rules` attribute for `Form` component, pass validation rules, and
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Activity form" name="desc">
|
<a-form-item label="Activity form" name="desc">
|
||||||
<a-textarea v-model:value="formState.desc" />
|
<a-textarea v-model:value="formState.desc" />
|
||||||
</a-form-item>
|
</a-form-item> -->
|
||||||
<a-form-item :wrapper-col="{ span: 14, offset: 4 }">
|
<a-form-item :wrapper-col="{ span: 14, offset: 4 }">
|
||||||
<a-button type="primary" @click="onSubmit">Create</a-button>
|
<a-button type="primary" @click="onSubmit">Create</a-button>
|
||||||
<a-button style="margin-left: 10px" @click="resetForm">Reset</a-button>
|
<a-button style="margin-left: 10px" @click="resetForm">Reset</a-button>
|
||||||
|
@ -131,6 +132,12 @@ export default defineComponent({
|
||||||
rules,
|
rules,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
resetForm,
|
resetForm,
|
||||||
|
option: ref([
|
||||||
|
{
|
||||||
|
value: 'lucy',
|
||||||
|
label: 'Lucy',
|
||||||
|
},
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ import inputProps from './inputProps';
|
||||||
import { hasProp, getComponent, getOptionProps } from '../_util/props-util';
|
import { hasProp, getComponent, getOptionProps } from '../_util/props-util';
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
import { defaultConfigProvider } from '../config-provider';
|
||||||
import ClearableLabeledInput from './ClearableLabeledInput';
|
import ClearableLabeledInput from './ClearableLabeledInput';
|
||||||
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
|
|
||||||
export function fixControlledValue(value: string | number) {
|
export function fixControlledValue(value: string | number) {
|
||||||
if (typeof value === 'undefined' || value === null) {
|
if (typeof value === 'undefined' || value === null) {
|
||||||
|
@ -56,11 +57,13 @@ export default defineComponent({
|
||||||
...inputProps,
|
...inputProps,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
return {
|
return {
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
configProvider: inject('configProvider', defaultConfigProvider),
|
||||||
removePasswordTimeout: undefined,
|
removePasswordTimeout: undefined,
|
||||||
input: null,
|
input: null,
|
||||||
clearableInput: null,
|
clearableInput: null,
|
||||||
|
formItemContext,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -100,6 +103,7 @@ export default defineComponent({
|
||||||
handleInputBlur(e: Event) {
|
handleInputBlur(e: Event) {
|
||||||
this.isFocused = false;
|
this.isFocused = false;
|
||||||
this.onBlur && this.onBlur(e);
|
this.onBlur && this.onBlur(e);
|
||||||
|
this.formItemContext.onFieldBlur();
|
||||||
},
|
},
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
|
@ -138,6 +142,7 @@ export default defineComponent({
|
||||||
this.$emit('update:value', (e.target as HTMLInputElement).value);
|
this.$emit('update:value', (e.target as HTMLInputElement).value);
|
||||||
this.$emit('change', e);
|
this.$emit('change', e);
|
||||||
this.$emit('input', e);
|
this.$emit('input', e);
|
||||||
|
this.formItemContext.onFieldChange();
|
||||||
},
|
},
|
||||||
handleReset(e: Event) {
|
handleReset(e: Event) {
|
||||||
this.setValue('', () => {
|
this.setValue('', () => {
|
||||||
|
@ -240,6 +245,12 @@ export default defineComponent({
|
||||||
prefix,
|
prefix,
|
||||||
isFocused,
|
isFocused,
|
||||||
};
|
};
|
||||||
return <ClearableLabeledInput {...props} ref={this.saveClearableInput} />;
|
return (
|
||||||
|
<ClearableLabeledInput
|
||||||
|
{...props}
|
||||||
|
id={props.id ?? this.formItemContext.id.value}
|
||||||
|
ref={this.saveClearableInput}
|
||||||
|
/>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { defaultConfigProvider } from '../config-provider';
|
||||||
import { fixControlledValue, resolveOnChange } from './Input';
|
import { fixControlledValue, resolveOnChange } from './Input';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import PropTypes, { withUndefined } from '../_util/vue-types';
|
import PropTypes, { withUndefined } from '../_util/vue-types';
|
||||||
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
|
|
||||||
const TextAreaProps = {
|
const TextAreaProps = {
|
||||||
...inputProps,
|
...inputProps,
|
||||||
|
@ -24,10 +25,12 @@ export default defineComponent({
|
||||||
...TextAreaProps,
|
...TextAreaProps,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
return {
|
return {
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
configProvider: inject('configProvider', defaultConfigProvider),
|
||||||
resizableTextArea: null,
|
resizableTextArea: null,
|
||||||
clearableInput: null,
|
clearableInput: null,
|
||||||
|
formItemContext,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -71,6 +74,7 @@ export default defineComponent({
|
||||||
this.$emit('update:value', (e.target as any).value);
|
this.$emit('update:value', (e.target as any).value);
|
||||||
this.$emit('change', e);
|
this.$emit('change', e);
|
||||||
this.$emit('input', e);
|
this.$emit('input', e);
|
||||||
|
this.formItemContext.onFieldChange();
|
||||||
},
|
},
|
||||||
handleChange(e: Event) {
|
handleChange(e: Event) {
|
||||||
const { value, composing, isComposing } = e.target as any;
|
const { value, composing, isComposing } = e.target as any;
|
||||||
|
@ -103,6 +107,10 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange);
|
resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange);
|
||||||
},
|
},
|
||||||
|
handleBlur(e: Event) {
|
||||||
|
this.$emit('blur', e);
|
||||||
|
this.formItemContext.onFieldBlur();
|
||||||
|
},
|
||||||
|
|
||||||
renderTextArea(prefixCls: string) {
|
renderTextArea(prefixCls: string) {
|
||||||
const props = getOptionProps(this);
|
const props = getOptionProps(this);
|
||||||
|
@ -118,7 +126,13 @@ export default defineComponent({
|
||||||
onChange: this.handleChange,
|
onChange: this.handleChange,
|
||||||
onKeydown: this.handleKeyDown,
|
onKeydown: this.handleKeyDown,
|
||||||
};
|
};
|
||||||
return <ResizableTextArea {...resizeProps} ref={this.saveTextArea} />;
|
return (
|
||||||
|
<ResizableTextArea
|
||||||
|
{...resizeProps}
|
||||||
|
id={resizeProps.id ?? this.formItemContext.id.value}
|
||||||
|
ref={this.saveTextArea}
|
||||||
|
/>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import PropTypes from '../_util/vue-types';
|
||||||
import { tuple } from '../_util/type';
|
import { tuple } from '../_util/type';
|
||||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
import omit from '../_util/omit';
|
import omit from '../_util/omit';
|
||||||
|
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||||
|
|
||||||
type RawValue = string | number;
|
type RawValue = string | number;
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ const Select = defineComponent({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: selectProps(),
|
props: selectProps(),
|
||||||
SECRET_COMBOBOX_MODE_DO_NOT_USE: 'SECRET_COMBOBOX_MODE_DO_NOT_USE',
|
SECRET_COMBOBOX_MODE_DO_NOT_USE: 'SECRET_COMBOBOX_MODE_DO_NOT_USE',
|
||||||
emits: ['change', 'update:value'],
|
emits: ['change', 'update:value', 'blur'],
|
||||||
slots: [
|
slots: [
|
||||||
'notFoundContent',
|
'notFoundContent',
|
||||||
'suffixIcon',
|
'suffixIcon',
|
||||||
|
@ -61,7 +62,7 @@ const Select = defineComponent({
|
||||||
],
|
],
|
||||||
setup(props, { attrs, emit, slots, expose }) {
|
setup(props, { attrs, emit, slots, expose }) {
|
||||||
const selectRef = ref();
|
const selectRef = ref();
|
||||||
|
const formItemContext = useInjectFormItemContext();
|
||||||
const focus = () => {
|
const focus = () => {
|
||||||
if (selectRef.value) {
|
if (selectRef.value) {
|
||||||
selectRef.value.focus();
|
selectRef.value.focus();
|
||||||
|
@ -99,6 +100,11 @@ const Select = defineComponent({
|
||||||
const triggerChange = (...args: any[]) => {
|
const triggerChange = (...args: any[]) => {
|
||||||
emit('update:value', args[0]);
|
emit('update:value', args[0]);
|
||||||
emit('change', ...args);
|
emit('change', ...args);
|
||||||
|
formItemContext.onFieldChange();
|
||||||
|
};
|
||||||
|
const handleBlur = (e: InputEvent) => {
|
||||||
|
emit('blur', e);
|
||||||
|
formItemContext.onFieldBlur();
|
||||||
};
|
};
|
||||||
expose({
|
expose({
|
||||||
blur,
|
blur,
|
||||||
|
@ -113,6 +119,7 @@ const Select = defineComponent({
|
||||||
dropdownClassName,
|
dropdownClassName,
|
||||||
virtual,
|
virtual,
|
||||||
dropdownMatchSelectWidth,
|
dropdownMatchSelectWidth,
|
||||||
|
id = formItemContext.id.value,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const { renderEmpty, getPopupContainer: getContextPopupContainer } = configProvider;
|
const { renderEmpty, getPopupContainer: getContextPopupContainer } = configProvider;
|
||||||
|
@ -175,6 +182,8 @@ const Select = defineComponent({
|
||||||
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
||||||
dropdownClassName={rcSelectRtlDropDownClassName}
|
dropdownClassName={rcSelectRtlDropDownClassName}
|
||||||
onChange={triggerChange}
|
onChange={triggerChange}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
id={id}
|
||||||
dropdownRender={selectProps.dropdownRender || slots.dropdownRender}
|
dropdownRender={selectProps.dropdownRender || slots.dropdownRender}
|
||||||
v-slots={{ option: slots.option }}
|
v-slots={{ option: slots.option }}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// debugger tsx
|
// debugger tsx
|
||||||
import Demo from '../../components/form/demo/index.vue';
|
import Demo from '../../components/form/demo/validation.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
render() {
|
render() {
|
||||||
|
|
Loading…
Reference in New Issue