vue2+elementui,动态生成的表单校验

话不多,先上一段视频,看看是不是你们需要的效果

elementui动态生成表单校验

附上代码

html 复制代码
<template>
	<div class="home">
		<div class="home-box">
			<!-- <menuHtml></menuHtml> -->
			<div class="home-div">
				<div style="margin-top: 20px;display:flex;justify-content: space-between;">
					<div>
						<span class="blueBlock">&nbsp;</span>
						<span class="title">问卷编辑</span>
					</div>
					<div>
						<span style="color:#F56C6C;">问卷编辑完成,千万不要忘记点击保存哦<i class="el-icon-thumb"
								style="transform: rotate(90deg);"></i></span>
						<el-button type="primary" plain size="mini" icon="el-icon-s-claim"
							@click="save('form')">保存</el-button>
					</div>
				</div>
				<el-form abel-position='top' :model="form" ref="form">
					<div class="content">
						<div class="content-top">
							<el-form-item prop="title" :rules="{required: true, message: '  ', trigger: 'blur' }">
								<el-input size="small" v-model="form.title" placeholder="请输入问卷标题">
									<el-button slot="append" @click="addQuestion()" icon="el-icon-circle-plus-outline">
										添加问题
									</el-button>
								</el-input>
							</el-form-item>
						</div>
						<div class="content-box">
							<div class="content-center" v-for="(question,index) in form.questionList">
								<el-form-item>
									<el-radio v-model="question.type" :label="1">单选</el-radio>
									<el-radio v-model="question.type" :label="2">多选</el-radio>
									<el-radio v-model="question.type" :label="3">开放式问题</el-radio>
								</el-form-item>
								<el-form-item class="question" :prop="'questionList.'+index+'.name'"
									:rules="{required: true, message: '', trigger: 'blur' }">
									<el-input placeholder="请输入问题" size="small" v-model="question.name">
										<template slot="prepend">Q{{index+1}}.</template>
									</el-input>
									<div @click="delQuestion(index)">
										<i class="el-icon-delete-solid"></i>
										<span>删除</span>
									</div>
								</el-form-item>
								<el-form-item v-if="question.type==3" :prop="'questionList.'+index+'.answer2'"
									:rules="{required: true, message: '  ', trigger: 'blur' }">
									<el-input type="textarea" :rows="4" placeholder="请输入答案" v-model="question.answer2"
										resize="none"></el-input>
								</el-form-item>
								<el-form-item v-else>
									<div class="answer" v-for="(answer,index1) in question.answerList">
										<el-form-item :prop="'questionList.'+index+'.answerList.'+index1+'.name'" :rules="{required: true, message: '  ', trigger: 'blur' }">
											<el-input size="small" placeholder="请输入答案" v-model="answer.name">
												<template slot="prepend">{{chars[index1]}}.</template>
											</el-input>
										</el-form-item>
										<div class="answer-right">
											<el-button @click="delAnswer(index,index1,question)" size="mini"
												icon="el-icon-minus" circle type="danger" plain></el-button>
											<el-button v-if="question.answerList.length==index1+1"
												@click="addAnswer(index,index1)" size="mini" icon="el-icon-plus" circle
												type="primary" plain></el-button>
										</div>
									</div>

								</el-form-item>
								<el-form-item label="正确答案" v-if="question.type==1" 
								 :prop="'questionList.'+index+'.answer'" :rules="{required: true, message: '  ', trigger: 'blur' }">
									<el-select size="mini" v-model="question.answer" placeholder="请选择答案">
										<el-option v-for="(item,index2) in question.answerList" :key="index2"
											:label="chars[index2]" :value="index2">
										</el-option>
									</el-select>

								</el-form-item>
								<el-form-item label="正确答案" v-if="question.type==2"
								:prop="'questionList.'+index+'.answer1'" :rules="{required: true, message: '  ', trigger: 'blur' }">
									<el-select size="mini" multiple v-model="question.answer1" placeholder="请选择答案">
										<el-option v-for="(item,index2) in question.answerList" :key="index2"
											:label="chars[index2]" :value="index2">
										</el-option>
									</el-select>
								</el-form-item>


							</div>
						</div>
					</div>
				</el-form>
			</div>

		</div>
	</div>
</template>

<script>
	// import menuHtml from '../../../view/leaf-content/menuHtml.vue'
	export default {
		name: 'addWjByTeacher',
		components: {
			// menuHtml,
		},
		props: [],
		data() {
			return {
				chars: ['A', 'B', 'C', 'D'],
				form: {
					title: '',
					// questionList: [],
					questionList: [{
						type: 1, //1.单选,2:多选,3开放式问题
						questionTitle: '',
						answerList: [{}],
						answer: '', //单选答案
						answer1: [], //多选答案
						answer2: '', //开放式问题答案
					}, {
						type: 2, //1.单选,2:多选,3开放式问题
						questionTitle: '',
						answerList: [{}],
						answer: '',
						answer1: [],
						answer2: '',
					}, {
						type: 3, //1.单选,2:多选,3开放式问题
						questionTitle: '',
						answerList: [{}],
						answer: '',
						answer1: [],
						answer2: '',
					}],
				}
			}

		},
		methods: {
			addQuestion() { //添加问题
				this.form.questionList.push({
					type: 1, //1.单选,2:多选,3开放式问题
					questionTitle: '',
					answerList: [{}],
					answer: '',
				});
			},
			delQuestion(index) { //删除问题
				this.form.questionList.splice(index, 1);
			},
			addAnswer(questionIndex, answerIndex) { //添加答案
				console.log(answerIndex);
				if (answerIndex < 3) {
					this.form.questionList[questionIndex].answerList.push({});
				}
			},
			delAnswer(questionIndex, answerIndex, question) { //删除答案
				if (answerIndex >= 1) {
					this.form.questionList[questionIndex].answerList.splice(answerIndex, 1);
				}
				//判断单选还是多选,要一同清空掉答案
				if (question.type == 1) {
					// this.form.questionList[questionIndex].answerList
					question.answer = "";
				} else if (question.type == 2) {
					question.answer1 = "";
				}
			},
			save(formName) { //保存问题
				this.$refs[formName].validate((valid) => {
					if (valid) {
						alert('submit!');
					} else {
						console.log('error submit!!');
						return false;
					}
				});
			},
		},
		mounted() {

		},
		destroyed() {

		},
		created() {

		}

	}
</script>

<style scoped>
	@import '../../../../assets/css/screenBase.css';

	.home {
		margin-top: 100px;
	}

	.home-box {
		margin: 0 auto;
		display: flex;
		align-items: flex-start;
		width: 1000px;
		justify-content: center
	}

	.home-div {
		width: 1000px;
		height: 650px;
		background-color: #fff;
		border-radius: 10px;
		/* 	padding-top: 20px; */
		padding-right: 40px;
		padding-left: 40px;

		/* padding-bottom: 20px; */
	}

	.blueBlock {
		height: 8px;
		width: 2px;
		background-color: #226cd3;
		margin-right: 10px;
	}

	.title {
		font-weight: 600;
		font-size: 24px;
	}

	.content {
		display: flex;
		flex-direction: column;
		align-items: flex-start;
		width: 900px;

	}

	.el-form-item {
		margin-bottom: 0px;
	}

	.content-top {

		margin-top: 20px;
		display: flex;
	}

	.content-top /deep/ input {
		width: 800px;
	}

	.content-center {
		width: 880px;
		background-color: #e9f5f136;
		border-radius: 10px;
		margin-top: 5px;
		padding: 10px;
		box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
	}

	.content-box {
		/* margin-top: 20px; */
		padding: 5px;
		height: 500px;
		overflow: hidden;
		overflow-y: auto;

	}

	/deep/.el-form--label-top .el-form-item__label {
		padding: 0px;
	}

	.btn {
		margin-top: 40px;
		text-align: center;
	}

	.question {}

	.question /deep/.el-form-item__content {
		display: flex;
		align-items: flex-start;
		justify-content: flex-start;
	}

	/* .answer /deep/.el-form-item__content {
		display: flex;
		align-items: flex-start;
		justify-content: flex-start;
		width: 750px;
	} */

	.question /deep/ input {
		width: 550px;
	}

	.question div {
		width: 100px;
		text-align: center;
	}

	.question i {
		color: #F56C6C;
		margin-right: 5px;
	}

	.answer /deep/ .el-input-group--prepend {
		width: 500px;
	}

	.answer /deep/ .el-input__inner {
		width: 500px;
	}

	.answer-right {
		width: 100px;
		display: flex;
		align-items: flex-start;
		/* text-align: center; */
	}

	.answer-right span {
		width: 25px;
		height: 25px;
		line-height: 25px;
		text-align: center;
		display: inline-block;
		background: #FFFFFF;
		border-radius: 8px;
		border: 1px solid #CCD3E7;

	}

	.answer-right i {
		color: #000;
		font-weight: 600;
	}

	.answer {
		display: flex;
		align-items: center;
	}
</style>

最主要的地方,因为我是双层的循环遍历,先看第一层的注意地方

最最最最最最最主要的地方,这是第二层的地方

相关推荐
Simaoya21 分钟前
vue process.env.VUE_APP_BASE_API的相关配置及axios简单封装
前端·javascript·vue.js
特立独行的猫a35 分钟前
Pinia:Vue 2 和 Vue 3 中更好用的状态管理框架
前端·javascript·vue.js·pinia·vuex
奋斗吧程序媛1 小时前
(接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
前端·javascript·vue.js
YANG-Live1 小时前
数据列表组件-报表
开发语言·javascript
narukeu2 小时前
理解 React 的严格模式
前端·javascript·react.js
卓卓没头发2 小时前
掌握Vue插槽:创建灵活且可复用的组件
前端·javascript·vue.js
hlyling3 小时前
一键高效处理,批量缩放PNG图片,按比例轻松调整,高效工作从此开始!
javascript·python·c#·objective-c·batch·symfony
用户4099322502123 小时前
Nuxt框架中内置组件详解及使用指南(三)
前端·vue.js·nuxt.js
不如吃茶去4 小时前
一文搞懂React Hooks闭包问题
前端·javascript·react.js
冯宝宝^4 小时前
图书管理系统
服务器·数据库·vue.js·spring boot·后端