vue3 +elementplus | vue2+elementui 动态地通过验证规则子新增或删除单个表单字段

效果图

点击 '+' 新增一行,点击'-' 删除一行

vue3+elementplus写法

template

javascript 复制代码
<el-dialog v-model="dialogFormVisible" :title="title">
            <el-form ref="ruleFormRef" :model="form" :inline="true" label-width="120px" class="demo-ruleForm"
                :size="formSize" status-icon>
                <el-form-item label="教师编号:" prop="code" :rules="[{ required: true, message: '请输入教师编号', trigger: 'blur' },
                { min: 4, message: '长度不能少于四位', trigger: 'blur' }]">
                    <el-input v-model="form.code" />
                </el-form-item>
                <el-form-item label="教师姓名:" prop="name" :rules="[{ required: true, message: '请输入教师姓名', trigger: 'blur' }]">
                    <el-input v-model="form.name" />
                </el-form-item>
                <div v-for="(item, index) in form.addList" :key="item.key" flex>
                    <!--注意:官方给的例子是用form的addList 去作为prop的标记  -->
                    <el-form-item label="授课院系:" :prop="'addList.' + index + '.yuanxi'" :rules="{
                        required: true,
                        message: '授课院系不能为空',
                        trigger: 'change',
                    }">
                        <el-select v-model="item.yuanxi" placeholder="请选择" @change="chooseClass(index)">
                            <el-option :label="yx.department" :value="yx.id" v-for="(yx, indexyx) in departmentList"
                                :key="indexyx"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="授课班级:" :prop="'addList.' + index + '.banji'" :rules="{
                        required: true,
                        message: '授课班级不能为空',
                        trigger: 'change',
                    }">
                        <el-select v-model="item.banji" placeholder="请选择">
                            <el-option :label="bj.class_title" :value="bj.id" v-for="(bj, indexbj) in item.classesList"
                                :key="indexbj"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-icon :size="26" color="#264E71" @click="removeOne(index)">
                        <Remove />
                    </el-icon>
                    <el-icon :size="26" color="#264E71" @click="plusOne(index)">
                        <CirclePlus />
                    </el-icon>

                </div>

                <el-form-item>
                    <el-button type="primary" @click="submitForm(ruleFormRef)">提交
                    </el-button>
                    <el-button @click="resetForm(ruleFormRef)">重置</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>

js

javascript 复制代码
<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { EpPropMergeType } from 'element-plus/es/utils';
import { departmentDepartmentList, departmentClassesList } from '../../request/api'
import { DepartmentListtype } from '~/type/login';
import userMainStore from "../../store/modules/app";
const mainStore = userMainStore();
import { CirclePlus, Remove } from '@element-plus/icons-vue';


const props = defineProps({
    title: {
        default: '',
        type: String,
    },
})

const dialogFormVisible = ref(false)
interface addlistType {
    yuanxi: string,
    banji: string,
    classesList: any,
    key: number

}
interface RuleForm {
    code: string,
    name: string,
    addList: addlistType[]
}
const formSize = ref<EpPropMergeType<StringConstructor, "" | "default" | "small" | "large", unknown> | undefined>('default')
const ruleFormRef = ref<FormInstance>()
const form = reactive<RuleForm>({
    code: '',
    name: '',
    addList: [
        {
            yuanxi: '',
            banji: '',
            classesList: [],
            key: Date.now(),
        }
    ]
})
const plusOne = (index: number) => {
    form.addList.push(
        {
            yuanxi: "",
            banji: '',
            classesList: [],
            key: Date.now(),
        }
    )
    console.log(form, 'form00000');

}
const removeOne = (index: number) => {
    form.addList.splice(index, 1)
}
let departmentList = ref([] as any[])
const chooseClass = (index: number) => {

     form.addList[index].classesList = []
     form.addList[index].banji = ''

    classes(index)

}
const classes = (index: number) => {
    let params = {
        token: mainStore.Authorization,
        limit: 1000,
        department: form.addList[index].yuanxi

    };
    departmentClassesList(params).then((res) => {
        let { data, code } = res;
        if (code == 200) {
            form.addList[index].classesList = data.list
            console.log(form, 'form11111');
        }
    });
}

const submitForm = async (formEl: FormInstance | undefined) => {
    if (!formEl) return
    await formEl.validate((valid, fields) => {
        if (valid) {
            // console.log('submit!')
            console.log(form, 'form')

        } else {
            console.log('error submit!', fields)
        }
    })
}

const resetForm = (formEl: FormInstance | undefined) => {
    if (!formEl) return
    formEl.resetFields()
}
const showDio1 = () => {
    dialogFormVisible.value = true
}
const department = () => {
    let params: DepartmentListtype = {
        token: mainStore.Authorization,
        limit: 1000,
        page: 1

    };
    departmentDepartmentList(params).then((res) => {
        let { data, code } = res;
        if (code == 200) {
            departmentList.value = data.list


        }
    });
}
// 第二部:暴露方法
defineExpose({
    showDio1
})
onMounted(() => {
    department()
})
</script>

vue2+elementui 写法

template

javascript 复制代码
<el-dialog :title="title" :visible.sync="centerDialogVisible" width="806px" @close="closeDio()"
            v-if="centerDialogVisible">
            <div>
                <el-form ref="form" :inline="true" :model="form" label-width="120px">
                    <el-form-item label="教师编号:" prop="code" :rules="[
                        { required: true, message: '请输入教师编号', trigger: 'blur' },
                        { min: 4, message: '长度不能少于四位', trigger: 'blur' }
                    ]">
                        <el-input v-model="form.code" onkeyup="value=value.replace(/[\W]/g,'')"
                            placeholder="请输入教师编号"></el-input>
                    </el-form-item>
                    <el-form-item label="教师姓名:" prop="name" :rules="[
                        { required: true, message: '请输入教师姓名', trigger: 'blur' }
                    ]">
                        <el-input v-model="form.name" type="text" @input="
                            form.name = form.name.replace(
                                /[^\u4E00-\u9FA5]/g,
                                ''
                            )
                            " placeholder="请输入教师姓名"></el-input>
                    </el-form-item>
                    <div flex v-for="(item, index) in form.addList" :key="index">
                        <el-form-item label="授课院系:" :prop="'addList.' + index + '.yuanxi'" :rules="{
                            required: true, message: '授课院系不能为空', trigger: 'change'
                        }">
                            <el-select v-model="item.yuanxi" filterable placeholder="请选择" @change="chooseClass(index)">
                                <el-option :label="yx.department" :value="yx.id" v-for="(yx, indexyx) in departmentList"
                                    :key="indexyx"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="授课班级:" :prop="'addList.' + index + '.banji'" :rules="{
                            required: true, message: '授课班级不能为空', trigger: 'change'
                        }">
                            <div flex="cross:center">
                                <el-select v-model="item.banji" filterable placeholder="请选择"
                                    @change="changeClass(item.banji, item.yuanxi, index)">
                                    <el-option :label="bj.class_title" :value="bj.id"
                                        v-for="(bj, indexbj) in item.classesList" :key="indexbj"></el-option>
                                </el-select>
                            </div>
                        </el-form-item>
                        <span style="margin-top:5px; ">
                            <i class="el-icon-remove-outline" style="color: #264E71;" @click="removeOne(index)"
                                v-show="form.addList.length > 1"></i>
                            <i class="el-icon-circle-plus-outline" style="color: #264E71;" @click="plusOne(index)"></i>
                        </span>
                    </div>


                </el-form>
            </div>
            <span slot="footer" class="dialog-footer">
                <el-button class="dioSave btnOk dioBigSave" type="primary" @click="AddOrder('form')">提交</el-button>
                <el-button class="dioSave btnCancel dioBigSave" @click="resetForm1" v-if="flag == 0">重置</el-button>
                <el-button class="dioSave btnCancel dioBigSave" @click="resetForm1" v-if="flag == 1">重置</el-button>
            </span>
        </el-dialog>

js

javascript 复制代码
<script>
import {
    addTeacher,
    updateTeacher,
    departmentDepartmentList,
    departmentClassesList
} from '@/api/api';
export default {
    components: {},
    data() {
        return {
            form: {
                addList: [
                    {
                        yuanxi: "",

                        banji: '',
                        classesList: []

                    }
                ],
            },

            departmentList: [],


            centerDialogVisible: false,

        };
    },
    props: {
        title: {
            type: String
        },
        flag: {
            type: Number
        }
    },
    computed: {},
    watch: {

    },
    methods: {
        changeClass(banji, yuanxi, index) {
            console.log(banji, '---banji');
            console.log(yuanxi, 'yuanxi');

        },
        AddOrder(form) {


            this.$refs[form].validate((valid) => {
                if (valid) {
                    if (this.flag == 1) {
                        this.updatesubmit()
                    } else {
                        this.submit()
                    }

                } else {
                    console.log('error submit!!');
                    return false;
                }
            });

        },
        xunhuan() {

        },
        submit() {
            let department = []
            let classes = []

            this.form.addList = Array.from(new Set(this.form.addList.map(JSON.stringify))).map(JSON.parse);

            console.log(this.form.addList, 'addList');

            this.form.addList.forEach((item) => {
                department.push(item.yuanxi)
                classes.push(item.banji)
            })



            let params = {
                token: this.$store.state.Authorization,
                code: this.form.code,
                name: this.form.name,
                department: String(department),
                classes: String(classes),
                account: JSON.parse(localStorage.getItem('loginInfo')).account

            };

            addTeacher(params).then((res) => {
                let { data, code } = res;
                if (code == 200) {
                    this.$message.success('新增成功!')
                    this.form.code = ''
                    this.form.name = ''
                    this.form.addList = [
                        {
                            yuanxi: "",

                            banji: '',
                            classesList: []

                        }
                    ]
                    // this.$refs['form'].resetFields();
                    // this.resetForm()
                    this.centerDialogVisible = false
                    this.$emit('addNewSuccess', true)

                }
            });
        },

        updatesubmit() {

            let department = []
            let classes = []
            this.form.addList = Array.from(new Set(this.form.addList.map(JSON.stringify))).map(JSON.parse);
            this.form.addList.forEach((item) => {
                department.push(item.yuanxi)
                classes.push(item.banji)
            })


            let params = {
                token: this.$store.state.Authorization,
                code: this.form.code,
                name: this.form.name,
                department: String(department),
                classes: String(classes),
                account: JSON.parse(localStorage.getItem('loginInfo')).account,
                uid: this.editId

            };


            updateTeacher(params).then((res) => {
                let { data, code } = res;
                if (code == 200) {
                    this.$message.success('编辑成功!')
                    this.form.code = ''
                    this.form.name = ''
                    this.form.addList = [
                        {
                            yuanxi: "",

                            banji: '',
                            classesList: []

                        }
                    ]

                    this.centerDialogVisible = false
                    this.$emit('addNewSuccess', true)

                }
            });
        },
        closeDio() {
            console.log('执行');
            this.resetForm1()
        },
        resetForm0() {
            this.$refs['form'].resetFields();
            // this.form = {}
            // this.departmentList = []
            this.form.code = ''
            this.form.name = ''
            this.form.addList = [
                {
                    yuanxi: "",

                    banji: '',
                    classesList: []

                }
            ]

        },
        resetForm1() {
            this.form = {
                addList: [
                    {
                        yuanxi: "",

                        banji: '',
                        classesList: []

                    }
                ]
            }

        },
        showDio1() {
            this.centerDialogVisible = true

            this.department()
        },
        showDio(row) {
            this.centerDialogVisible = true

            // if (row) {
            console.log(row.id, 'row')
            this.editId = row.id
            // this.form.code = row.code
            // this.form.name = row.name
            if (row.clas) {
                let arrClasses = (row.classes).split(',')
                console.log(row.clas, 'clas');
                let arrdepartment = []
                row.clas.forEach((ele, i) => {
                    arrdepartment.push(ele.department_id)
                })
                let addList = []
                for (let i = 0; i < arrClasses.length; i++) {

                    addList.push(
                        {
                            yuanxi: '',
                            banji: Number(arrClasses[i]),
                            classesList: []

                        }
                    )

                }
                for (let j = 0; j < arrdepartment.length; j++) {
                    addList[j].yuanxi = Number(arrdepartment[j])
                }



                this.department()

                // this.form.addList = addList
                this.form = {
                    code: row.code,
                    name: row.name,
                    addList: addList
                }
                console.log(addList);
                arrClasses.forEach((item, index) => {
                    this.classes(index)
                })
            } else {
                this.form = {
                    code: row.code,
                    name: row.name,
                    addList: [
                        {
                            yuanxi: "",

                            banji: '',
                            classesList: []

                        }
                    ]
                }
            }


        },
        removeOne(index) {
            this.form.addList.splice(index, 1)
        },
        plusOne() {
            this.form.addList.push(
                {
                    yuanxi: "",
                    // departmentList: [],
                    banji: '',
                    classesList: []
                }
            )
        },
        // 院系
        department() {
            let params = {
                token: this.$store.state.Authorization,
                limit: 1000

            };
            departmentDepartmentList(params).then((res) => {
                let { data, code } = res;
                if (code == 200) {
                    this.departmentList = data.list


                }
            });

        },
        chooseClass(index) {
            this.form.addList[index].classesList = []
            this.form.addList[index].banji = ''

            this.classes(index)

        },
        classes(index) {
            let params = {
                token: this.$store.state.Authorization,
                limit: 1000,
                department: this.form.addList[index].yuanxi

            };
            departmentClassesList(params).then((res) => {
                let { data, code } = res;
                if (code == 200) {

                    this.form.addList[index].classesList = data.list

                }
            });

        },

    },
    created() {

    },
    mounted() {

    },
    beforeCreate() { },
    beforeMount() { },
    beforeUpdate() { },
    updated() { },
    beforeDestroy() { },
    destroyed() { },
    activated() { },
}
</script>
相关推荐
小村儿5 小时前
给 AI Agent 装上"长期记忆":Karpathy 的 LLM Wiki 思想,我做成了工具
前端·后端·ai编程
竹林8185 小时前
用ethers.js连接MetaMask实现Web3钱包登录:从踩坑到稳定运行的完整记录
前端·javascript
heyCHEEMS5 小时前
如何用 Recast 实现静态配置文件源码级读写
前端·node.js
心连欣5 小时前
从零开始,学习所有指令!
前端·javascript·vue.js
review445435 小时前
大模型和function calling分别是如何工作的
前端
东东同学5 小时前
耗时一个月,我把 Nuxt 首屏性能排障经验做成了一个 AI Skill
前端·agent
冴羽6 小时前
超越 Vibe Coding —— AI 辅助编程指南
前端·ai编程·vibecoding
梦想的颜色6 小时前
一天一个SKILL——前端最佳自动化测试 webapp-testing
前端·web app
SoaringHeart6 小时前
Flutter进阶:放弃 MediaQuery.of(context) 使用 NScreenManager
前端·flutter
openKaka_7 小时前
从 scheduleUpdateOnFiber 到 Root 微任务调度:React 如何把更新交给调度系统
开发语言·前端·javascript