引言
jeecg可以通过formSchema: FormSchema[]的方式快速定义表单字段
export const formSchema: FormSchema[] = [
{
label: "父级节点",
field: "pid",
component: "JTreeSelect",
componentProps: {
dict: "base_dictionary,name,id",
pidField: "pid",
pidValue: "0",
hasChildField: "has_child",
condition: '{"dict_type":"node"}',
}
},
{
label: "名称",
field: "name",
component: "Input"
},
{
label: "字典值",
field: "dictValue",
component: "Input"
},
{
label: "排序号,大号在前",
field: "orderNum",
component: "InputNumber"
},
]
但较为复杂的表单要怎么编写,比如表单里除了各个form-item,还要包含表格等组件。通过尝试,我找到一个解决方法。这里做个记录
方法一 —— 使用原生组件
完全使用vue+antdv的原生组件编码。但这样就不能使用jeecg内置的很多功能
方法二 —— 原生+jeecg组件
这里贴出template的代码。
最外层是弹窗,表单元素有原生的antdv组件:文本框、按钮、数字框;有jeecg组件:JTreeSelect、RadioButtonGroup、BasicTable
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
<a-form
:model="formData"
name="questionForm"
:label-col="{ span: 4 }"
autocomplete="off"
@finish="onFinish"
@finishFailed="onFinishFailed"
>
<a-form-item label="章节" name="chapterId" :rules="[{ required: true, message: '请选择章节!' }]">
<JTreeSelect v-model:value="formData.chapterId" v-bind="chapterIdProps" />
</a-form-item>
<a-form-item label="题目" name="title" :rules="[{ required: true, message: '请选择填写题目!' }]">
<a-input v-model:value="formData.title" />
</a-form-item>
<a-form-item label="题型" name="questionType" :rules="[{ required: true, message: '请选择题型!' }]">
<RadioButtonGroup v-model:value="formData.questionType" v-bind="questionTypeProps" size="small" />
</a-form-item>
<BasicTable
@register="register"
size="small"
:columns="optionColumns"
:dataSource="optionTableDataSource"
:bordered="true"
:pagination="false"
:beforeFetch="assembleOptionTableParams"
:api="listByQuestionId"
:actionColumn="optionActionColumn"
>
<template #action="{ record, column }">
<TableAction :actions="createActions(record, column)" />
</template>
</BasicTable>
<a-button type="dashed" block @click="addOption"><PlusOutlined />增加选项</a-button>
<a-form-item label="分值" name="score" :rules="[{ required: true, message: '请填写分值!' }]">
<a-input-number v-model:value="formData.score" />
</a-form-item>
</a-form>
</BasicModal>
</template>
页面显示了,下一步怎么走
页面能正常渲染、显示,但是下一步怎么走:
表单绑定数据?列表数据CRUD?单独修改某个字段?
直接上代码
const questionId = ref(""); //主数据id
const formData = ref<{}>({id: "",}); //表单数据
const optionTableDataSource = ref([]); //列表数据
//注册弹窗表单组件、表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
//重置表单
setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
let id = data.record.id || "";
if (id == "") {
return;
}
questionId.value = id;
await initFormValue(id);
});
//注册列表组件
const [register,{getDataSource, setTableData}] = useTable();
//加载表单数据
async function initFormValue(id) {
let ret = await getById({ id: id });
formData.value = ret;
}
//列表增加行。setTableData是useTable()定义的方法,要在上面注册列表组件是声明
function addOption() {
let newData = {
id: '',
title: '',
editable: true
}
setTableData([...newData]);
}
//加载列表数据前,增加额外的参数:主数据ID
function assembleOptionTableParams(params) {
let id = questionId.value;
params.questionId = id;
return false;
}
总结
表单赋值,通过vue的数据绑定实现。formData保存了表单数据
列表数据,通过列表的beforeFetch事件组装查询参数,然后通过api属性指定的方法加载数据
jeecg的封装还是花了很多心思的,能感受到作者的用心。后续有空再继续研究和分享