roymondchen b7c04edcd5 feat(form): 新增 validateOnInit,默认关闭初始化时自动校验
属性面板仍开启初始化校验,避免打开普通表单时立即展示错误态。
2026-07-28 16:45:42 +08:00

141 lines
3.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="m-form-box" :style="style">
<div class="m-box-body" :style="bodyHeight ? { height: `${bodyHeight}px` } : {}">
<TMagicScrollbar>
<Form
ref="form"
:size="size"
:disabled="disabled"
:config="config"
:init-values="values"
:parent-values="parentValues"
:label-width="labelWidth"
:label-position="labelPosition"
:inline="inline"
:prevent-submit-default="preventSubmitDefault"
:use-field-text-in-error="useFieldTextInError"
:extend-state="extendState"
:type-match-valid="typeMatchValid"
:validate-on-init="validateOnInit"
@change="changeHandler"
></Form>
<slot></slot>
</TMagicScrollbar>
</div>
<div class="dialog-footer" :style="`height: ${footerHeight}px`">
<div>
<slot name="left"></slot>
</div>
<div>
<slot name="footer">
<TMagicButton type="primary" :size="size" :disabled="disabled" :loading="saveFetch" @click="submitHandler">{{
confirmText
}}</TMagicButton>
</slot>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref, watchEffect } from 'vue';
import { TMagicButton, TMagicScrollbar } from '@tmagic/design';
import Form from './Form.vue';
import type { ContainerChangeEventData, FormConfig, FormState, FormValue } from './schema';
defineOptions({
name: 'MFormBox',
});
const props = withDefaults(
defineProps<{
config?: FormConfig;
values?: Object;
parentValues?: Object;
width?: number;
height?: number;
labelWidth?: string;
/** 是否开启类型匹配校验 */
typeMatchValid?: boolean;
/** 透传给内部 `MForm`,初始化完成后是否立即校验(默认 `false` */
validateOnInit?: boolean;
disabled?: boolean;
size?: 'small' | 'default' | 'large';
confirmText?: string;
inline?: boolean;
labelPosition?: string;
preventSubmitDefault?: boolean;
/** 透传给内部 `MForm`,控制表单校验失败时错误提示前缀是否使用字段的 text 文案 */
useFieldTextInError?: boolean;
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
}>(),
{
config: () => [],
values: () => ({}),
confirmText: '确定',
useFieldTextInError: true,
validateOnInit: false,
},
);
const emit = defineEmits<{
change: [v: any, eventData: ContainerChangeEventData];
submit: [v: any, eventData: ContainerChangeEventData];
error: [e: any];
}>();
const footerHeight = 60;
const style = computed(() => {
const style: { width?: string; height?: string } = {};
if (typeof props.width === 'number') {
style.width = `${props.width}px`;
}
if (typeof props.height === 'number') {
style.height = `${props.height}px`;
}
return style;
});
const form = ref<InstanceType<typeof Form>>();
const saveFetch = ref(false);
const bodyHeight = ref(0);
watchEffect(() => {
if (!props.height) {
return;
}
bodyHeight.value = props.height - footerHeight;
});
const submitHandler = async () => {
try {
const changeRecords = form.value?.changeRecords;
const values = await form.value?.submitForm();
emit('submit', values, { changeRecords });
} catch (e) {
emit('error', e);
}
};
const changeHandler = (value: FormValue, eventData: ContainerChangeEventData) => {
emit('change', value, eventData);
};
const show = () => {};
const hide = () => {};
defineExpose({
form,
saveFetch,
show,
hide,
});
</script>