重點:
1、父元件傳動态渲染的表單數組給子元件
2、動态表單校驗在子元件觸發校驗,把觸發校驗的方法暴露給父元件,在父元件送出表單的時候,調用子元件的方法
父元件子產品代碼
<template>
<el-card>
<el-form
ref="formTop"
:model="_form"
label-width="150px"
:inline="true"
:rules="formTopRule"
>
<el-form-item :label="t('Upper_Keyin_Limt')" prop="upperKeyinValue">
<el-input-number v-model="_form.upperKeyinValue" :controls="false" />
</el-form-item>
<el-form-item :label="t('Lower_Keyin_Limt')" prop="lowerKeyinValue">
<el-input-number v-model="_form.lowerKeyinValue" :controls="false" />
</el-form-item>
<el-form-item
style="
position: fixed;
bottom: 0;
right: 50%;
transform: translateX(-50%);
z-index: 1;
width: auto;
"
>
<div>
<el-button type="primary" @click="submitFormTop">{{
$t('options.save')
}}</el-button>
</div>
</el-form-item>
</el-form>
<el-collapse v-model="chartType.chartTypeArr" @change="handleChange">
<el-collapse-item title="Mean" name="Mean">
<formBottomArr
v-if="_form.spcChartDefaultUpdateVOList.length"
:formBottomArr="
_form.spcChartDefaultUpdateVOList.filter(
(item) => item.chartType < 5
)
"
ref="formMean"
/>
</el-collapse-item>
<el-collapse-item title="Single" name="Single">
<formBottomArr
v-if="_form.spcChartDefaultUpdateVOList.length"
:formBottomArr="
_form.spcChartDefaultUpdateVOList.filter(
(item) => item.chartType == 10 || item.chartType == 11
)
"
ref="formSingle"
/>
</el-collapse-item>
<el-collapse-item title="Count" name="Count">
<formBottomArr
v-if="_form.spcChartDefaultUpdateVOList.length"
:formBottomArr="
_form.spcChartDefaultUpdateVOList.filter(
(item) => item.chartType == 12
)
"
ref="formCount"
/>
</el-collapse-item>
</el-collapse>
</el-card>
</template>
<script lang="ts" setup>
import formBottomArr from '@/views/utility/SetChartformDefaultParameter/components/formBottomArr.vue';
import SetChartformDefaultParameter from '@/views/utility/SetChartformDefaultParameter/index.t';
import { formBottomType } from '@/types/api/group/chart';
import {
rules,
tabContentList,
} from '@/views/utility/SetChartformDefaultParameter/components/formRule';
import { getChartDefault, setChartDefault } from '@/api/group/chart';
import useLang from '@/hooks/useLang';
import { ElMessage } from 'element-plus';
import { ElForm } from 'element-plus';
const formTop = ref(ElForm);
const { t } = useLang({ ...SetChartformDefaultParameter });
const formMean: any = ref(null);//動态表單2
const formSingle: any = ref(null);//動态表單3
const formCount: any = ref(null);//動态表單4
const chartType = reactive({
chartTypeArr: ['Mean', 'Single', 'Count'],
});
const handleChange = () => {};
const submitFormTop = () => {
formTop.value.validate(async (valid: boolean) => {
if (valid) {
let flag1 = await formMean?.value?.onSave();
let flag2 = await formSingle?.value?.onSave();
let flag3 = await formCount?.value?.onSave();
if (flag1 && flag2 && flag3) {
await setChartDefault(_form);
ElMessage.success('儲存成功');
} else if (!flag1) {
chartType.chartTypeArr = ['Mean'];
} else if (!flag2) {
chartType.chartTypeArr = ['Single'];
} else {
chartType.chartTypeArr = ['Count'];
}
}
});
};
const formTopRule = reactive({
...rules(),
});
let _form = reactive({
lowerKeyinValue: 4,
upperKeyinValue: 4,
spcChartDefaultUpdateVOList: [] as formBottomType[],
});
onMounted(async () => {
const resData = await getChartDefault();
_form = Object.assign(_form, {
lowerKeyinValue: resData.data.lowerKeyinValue,
upperKeyinValue: resData.data.upperKeyinValue,
spcChartDefaultUpdateVOList: resData.data.spcChartDefaultQryVOList,
});
});
</script>
<style scoped>
:deep(.el-form-item__error) {
white-space: nowrap;
}
</style>
//formBottomArr.vue
//子元件formBottomArr動态表單代碼
<template>
<el-form
ref="formBottom"
:model="_form"
:rules="bottomrRules"
label-width="150px"
:inline="true"
>
<el-row :gutter="24">
<el-col :span="4" style="margin-top: 23px">
<div class="tabContent" v-for="item in labelArr.arr" :key="item.key">
{{ t(item.key) }}{{ item.value }}:
</div>
</el-col>
<el-col :span="20">
<el-row :gutter="20">
<el-col :span="6" v-for="(item, index) in _form.formBottomArr">
<div>
<span style="margin-left: 10px">{{
statusObj[item.chartType]
}}</span>
</div>
<el-form-item :prop="`formBottomArr.${index}.uplValue`">
<el-input-number
v-model="_form.formBottomArr[index].uplValue"
:controls="false"
/>
</el-form-item>
<el-form-item :prop="`formBottomArr.${index}.uslValue`">
<el-input-number
v-model="_form.formBottomArr[index].uslValue"
:controls="false"
/>
</el-form-item>
</el-col>
</el-row>
</el-col>
</el-row>
</el-form>
</template>
<script lang="ts" setup>
import chartForm from '@/views/chart/ChartForm.t';
import useLang from '@/hooks/useLang';
import { status } from '@/views/chart/chartFormRule';
import { BottomForm } from './BottomFormRule';
import { ElForm } from 'element-plus';
const formBottom = ref(ElForm);
const labelArr = reactive({
arr: [
{ key: 'Upper_Piot_Limit', value: '(UPL)' },
{ key: 'Upper_Spec_Limit', value: '(USL)' },
],
});
const { t } = useLang({ ...chartForm });
const statusObj = reactive({
...(status() as { [key: number]: string }),
});
const props = defineProps<{
formBottomArr: any;
}>();
const _form = reactive({
formBottomArr: props.formBottomArr,
});
const bottomrRules = computed(() => {
return BottomForm(props.formBottomArr);
});
const onSave = async () => {
return formBottom.value.validate((valid: boolean) => {
return valid;
});
};
defineExpose({
onSave,
});
</script>
<style scoped>
:deep(.el-checkbox) {
height: auto;
}
.tabContent {
height: 32px;
line-height: 32px;
margin: 0 0 18px;
}
</style>
表單校驗檔案
//BottomFormRule.ts
export function BottomForm(formBottomArr: any, form?: any) {
let rule = {} as any;
formBottomArr.forEach((item: any, index: number) => {
rule[`formBottomArr.${index}.uplValue`] = [
{
required: true,
message: '此項必填',
trigger: 'blur',
},
createRule(0, 99999999),
];
rule[`formBottomArr.${index}.uslValue`] = [
{
required: true,
message: '此項必填',
trigger: 'blur',
},
createRule(0, formBottomArr[index].uplValue),
];
});
// console.log(rule,"+rule")
return rule;
}
export const createRule = (min: number, max: number) => {
return {
validator: (rule: any, value: any, callback: any) =>
limitNumber(rule, value, callback, { min, max }),
trigger: 'blur',
};
};
export const limitNumber = (
rule: any,
value: any,
callback: any,
{ min, max }: { min?: number; max?: number }
) => {
if (min && value < min|| value == min) {
return callback(new Error(`此值不合規範`));
}
if ((max && value > max) || value == max) {
return callback(new Error(`此值不合規範`));
}
callback();
};