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