You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.2 KiB
106 lines
3.2 KiB
3 years ago
|
import type { ComputedRef, InjectionKey, ConcreteComponent } from 'vue';
|
||
|
import {
|
||
|
watch,
|
||
|
computed,
|
||
|
inject,
|
||
|
provide,
|
||
|
ref,
|
||
|
onBeforeUnmount,
|
||
|
getCurrentInstance,
|
||
|
defineComponent,
|
||
|
} from 'vue';
|
||
|
import devWarning from '../vc-util/devWarning';
|
||
|
|
||
|
export type FormItemContext = {
|
||
|
id: ComputedRef<string>;
|
||
|
onFieldBlur: () => void;
|
||
|
onFieldChange: () => void;
|
||
|
clearValidate: () => void;
|
||
|
};
|
||
|
|
||
|
type InternalFormItemContext = {
|
||
|
addFormItemField: (key: Symbol, type: ConcreteComponent) => void;
|
||
|
removeFormItemField: (key: Symbol) => void;
|
||
|
};
|
||
|
|
||
|
const ContextKey: InjectionKey<FormItemContext> = Symbol('ContextProps');
|
||
|
|
||
|
const InternalContextKey: InjectionKey<InternalFormItemContext> = Symbol('InternalContextProps');
|
||
|
|
||
|
export const useProvideFormItemContext = (
|
||
|
props: FormItemContext,
|
||
|
useValidation: ComputedRef<boolean> = computed(() => true),
|
||
|
) => {
|
||
|
const formItemFields = ref(new Map<Symbol, ConcreteComponent>());
|
||
|
const addFormItemField = (key: Symbol, type: ConcreteComponent) => {
|
||
|
formItemFields.value.set(key, type);
|
||
|
formItemFields.value = new Map(formItemFields.value);
|
||
|
};
|
||
|
const removeFormItemField = (key: Symbol) => {
|
||
|
formItemFields.value.delete(key);
|
||
|
formItemFields.value = new Map(formItemFields.value);
|
||
|
};
|
||
|
const instance = getCurrentInstance();
|
||
|
watch([useValidation, formItemFields], () => {
|
||
|
if (process.env.NODE_ENV !== 'production') {
|
||
|
if (useValidation.value && formItemFields.value.size > 1) {
|
||
|
devWarning(
|
||
|
false,
|
||
|
'Form.Item',
|
||
|
`FormItem can only collect one field item, you haved set ${[
|
||
|
...formItemFields.value.values(),
|
||
|
]
|
||
|
.map(v => `\`${v.name}\``)
|
||
|
.join(', ')} ${formItemFields.value.size} field items.
|
||
|
You can set not need to be collected fields into \`a-form-item-rest\``,
|
||
|
);
|
||
|
let cur = instance;
|
||
|
while (cur.parent) {
|
||
|
console.warn('at', cur.type);
|
||
|
cur = cur.parent;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
provide(ContextKey, props);
|
||
|
provide(InternalContextKey, {
|
||
|
addFormItemField,
|
||
|
removeFormItemField,
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const defaultContext: FormItemContext = {
|
||
|
id: computed(() => undefined),
|
||
|
onFieldBlur: () => {},
|
||
|
onFieldChange: () => {},
|
||
|
clearValidate: () => {},
|
||
|
};
|
||
|
const defaultInternalContext: InternalFormItemContext = {
|
||
|
addFormItemField: () => {},
|
||
|
removeFormItemField: () => {},
|
||
|
};
|
||
|
export const useInjectFormItemContext = () => {
|
||
|
const internalContext = inject(InternalContextKey, defaultInternalContext);
|
||
|
const formItemFieldKey = Symbol('FormItemFieldKey');
|
||
|
const instance = getCurrentInstance();
|
||
|
internalContext.addFormItemField(formItemFieldKey, instance.type);
|
||
|
onBeforeUnmount(() => {
|
||
|
internalContext.removeFormItemField(formItemFieldKey);
|
||
|
});
|
||
|
// We should prevent the passing of context for children
|
||
|
provide(InternalContextKey, defaultInternalContext);
|
||
|
provide(ContextKey, defaultContext);
|
||
|
return inject(ContextKey, defaultContext);
|
||
|
};
|
||
|
|
||
|
export default defineComponent({
|
||
|
name: 'AFormItemRest',
|
||
|
setup(_, { slots }) {
|
||
|
provide(InternalContextKey, defaultInternalContext);
|
||
|
provide(ContextKey, defaultContext);
|
||
|
return () => {
|
||
|
return slots.default?.();
|
||
|
};
|
||
|
},
|
||
|
});
|