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>

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

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

相关推荐
学不会•26 分钟前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS1 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜3 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点3 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow3 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o3 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
刚刚好ā4 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
yqcoder5 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
会发光的猪。6 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客6 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js