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>
相关推荐
余道各努力,千里自同风几秒前
前端 vue 如何区分开发环境
前端·javascript·vue.js
PandaCave7 分钟前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
软件小伟9 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾31 分钟前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧39 分钟前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7011 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue
疯狂的沙粒2 小时前
对 TypeScript 中高级类型的理解?应该在哪些方面可以更好的使用!
前端·javascript·typescript