一、分步最后一步提交——v-if
将form表单写在一个页面,一张表,只切换里面的el-form-item
实现思路:
? ? ? ? 点击下一步:进行表格验证 检验通过下一步——想对应的active(步骤step的值)进行加加,因为这里只有三步 所以最后一步的时候 active直接为2 ,切按钮变为“提交”
? ? ? ? 点击提交:进行表单校验后 将数据传给后台 返回成功后 关闭弹层,表单数据初始化
? ? ? ? 点击上一步:相应步骤的值active减减,直到第一步,active=0
?在实现过程中遇到一下问题(表单验证时)
? ? ? ? 1、切换表单 部分验证失效 ——(第一步的input有验证,最后一步input 验证失效)
? ? ? ? ? ? ? ? 解决:将<template>标签切换改成<div>
? ? ? ? 2、提交表单后做数据初始化,弹层关闭——在打开弹层时,校验自动显示了,且验证第一个input对应了最后一个验证。
? ? ? ? 解决:因为一开始是使用 object.assign(this.$data,this.$options.data())进行初始化的,出现了以上问题,尝试在每个切换处加“key”后有点效果,但控制台会报“验证的一些错误。
????????最后使用object.assign(this.$data.form,this.$options.data().form)进行表单form初始化,this.active = 0 (步骤初始化),关闭弹层。就没问题了
?表单值初始化,我不想一个个那么赋值,才想着使用Object.assign()方法。不知道大佬们有没有更好的方法,求指导。
效果图
?
完整代码
<template>
<el-dialog title="提示" :visible.sync="dialogVisible" width="50%">
<el-steps :active="active" finish-status="success">
<el-step title="If步骤 1"></el-step>
<el-step title="If步骤 2"></el-step>
<el-step title="If步骤 3"></el-step>
</el-steps>
<div>
<el-form ref="ruleForm" :model="form" :rules="rules" label-width="100px">
<div v-if="active === 0">
<el-form-item label="密码" prop="pass">
<el-input
type="password"
v-model="form.pass"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input
type="password"
v-model="form.checkPass"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model.number="form.age"></el-input>
</el-form-item>
<el-form-item>
<!-- <el-button type="primary" @click="submitForm('form')">提交</el-button>
<el-button @click="resetForm('form')">重置</el-button> -->
</el-form-item>
</div>
<div v-if="active === 1">
<el-form-item label="活动名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动区域" prop="regionActive">
<el-select v-model="form.regionActive" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-form-item prop="date1">
<el-date-picker
type="date"
placeholder="选择日期"
v-model="form.date1"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-form-item prop="date2">
<el-time-picker
placeholder="选择时间"
v-model="form.date2"
style="width: 100%"
></el-time-picker>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="即时配送" prop="delivery">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="活动性质" prop="type">
<el-checkbox-group v-model="form.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊资源" prop="resource">
<el-radio-group v-model="form.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动形式" prop="desc">
<el-input type="textarea" v-model="form.desc"></el-input>
</el-form-item>
</div>
<div v-if="active === 2">
<el-form-item label="审批人" prop="users">
<el-input v-model="form.users" placeholder="审批人"></el-input>
</el-form-item>
<el-form-item label="活动区域">
<el-select v-model="form.region" placeholder="活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<!-- <el-button type="primary" @click="onSubmit">查询</el-button> -->
</el-form-item>
</div>
</el-form>
</div>
<div slot="footer">
<el-button v-if="active === 2" @click="submit">提交</el-button>
<el-button v-else @click="next">保存并下一步</el-button>
<el-button @click="pre">上一步</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
data() {
return {
dialogVisible: false,
active: 0,
form: {
users: "",
region: "",
name: "",
regionActive: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: "",
pass: "",
checkPass: "",
age: "",
},
rules: {
pass: [{ required: true, message: "密码不能为空", trigger: "blur" }],
desc: [
{ required: true, message: "活动形式不能为空", trigger: "blur" },
],
users: [{ required: true, message: "shenp", trigger: "blur" }],
type: [
{
type: "array",
required: true,
message: "请至少选择一个活动性质",
trigger: "change",
},
],
resource: [
{ required: true, message: "请选择活动资源", trigger: "change" },
],
},
};
},
methods: {
showDailog() {
this.dialogVisible = true;
},
async submit() {
let that = this;
try {
const check = await this.$refs["ruleForm"].validate();
console.log(check, "检验布尔");
setTimeout(() => {
this.$message.success("提交表格成功");
// that.$refs["ruleForm"].clearValidate();
// this.dialogVisible = false;
// let obj = {
// users: "",
// region: "",
// name: "",
// regionActive: "",
// date1: "",
// date2: "",
// delivery: false,
// type: [],
// resource: "",
// desc: "",
// pass: "",
// checkPass: "",
// age: "",
// }
// this.form = obj
this.active = 0;
this.dialogVisible = false;
Object.assign(that.$data.form, that.$options.data().form); // 单个form 初始
// Object.assign(that.$data, that.$options.data()) 所以数据初始,使用这个 再打开弹层时验证显示会有问题 加key缓解
}, 500);
} catch (error) {
console.log(error, "校验");
}
console.log(this.form, "form提交");
},
async next() {
try {
const check = await this.$refs["ruleForm"].validate();
console.log(check, "检验布尔");
if (this.active++ === 2) this.active = 2;
} catch (error) {
console.log(error, "校验");
}
console.log(this.form, "this.form下一步");
// 进行表格校验成功后再到下一步
},
pre() {
if (this.active-- === 0) this.active = 0;
console.log(this.form, "this.form上一步");
},
},
};
</script>
<style>
</style>
二、组件切换 做 步骤
?小说明——原先就是使用的component 组件切换做分步,最后一步进行提交,然后慢慢搞复杂了
这里就简单记记我当初用component的心路
思路:
1、定义三个组价 form1、form2、form3? 和一个组件切换页formdailog.vue。在formdailog页面使用<componet is="组件名”/> 进行切换,定义表单的所有属性allForm 传值进组件
?
?这里的一些方法逻辑都在各自组件里,通过ref来调用方法
?这里直接上代码了
formdailog.vue
<template>
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
<div v-loading="loading" element-loading-text="提交中">
<el-steps :active="active" finish-status="success">
<el-step title="步骤 1"></el-step>
<el-step title="步骤 2"></el-step>
<el-step title="步骤 3"></el-step>
</el-steps>
<div class="form">
<!-- <formOne v-if="active==0"/>
<formTwo v-if="active==1"/>
<formThree v-if="active==2"/> -->
<keep-alive>
<component
:is="flag"
ref="componetRef"
:formInline="allForm"
:form="allForm"
:ruleForm="allForm"
></component>
</keep-alive>
</div>
<el-button
type=""
v-if="this.flag === 'formThree'"
style="margin-top: 12px"
@click="submit"
>提交</el-button
>
<el-button v-else style="margin-top: 12px" @click="next"
>保存并下一步</el-button
>
<el-button style="margin-top: 12px" @click="last">上一步</el-button>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</div>
</el-dialog>
</template>
<script>
import formOne from "./form/form1.vue";
import formTwo from "./form/form2.vue";
import formThree from "./form/form3.vue";
export default {
components: {
formOne,
formTwo,
formThree,
},
data() {
return {
dialogVisible: false,
active: 0,
loading: false,
flag: "formOne",
allForm: {
user: "",
region: "",
name: "",
regionActive: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: "",
pass: "",
checkPass: "",
age: "",
},
};
},
methods: {
showDailog() {
this.dialogVisible = true;
},
async next() {
const check = await this.$refs["componetRef"].submitForm("ruleForm");
if (!check) {
return;
}
if (this.active++ >= 2) this.active = 2;
switch (this.active) {
case 0:
this.flag = "formOne";
break;
case 1:
this.flag = "formTwo";
break;
case 2:
this.flag = "formThree";
break;
}
},
last() {
this.active--;
switch (this.active) {
case 0:
this.flag = "formOne";
break;
case 1:
this.flag = "formTwo";
break;
case 2:
this.flag = "formThree";
break;
}
},
//提交按钮—— 最后提交也掉子组件方法验证
async submit() {
let that = this
const check = await this.$refs["componetRef"].submitForm("ruleForm");
if (!check) {
return;
}
try {
await this.$confirm("是否提交表单, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
});
this.active = 3;
this.loading = true;
setTimeout(() => {
this.loading = false;
this.$message.success("提交表单成功");
this.dialogVisible = false;
Object.assign(this.$data, this.$options.data())
this.active = 0
}, 3000);
} catch (error) {
this.active = 2;
this.$message.error("取消提交");
}
},
},
};
</script>
<style>
</style>
form1.vue
<template>
<div class="form3">
<el-form
:model="ruleForm"
status-icon
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="密码" prop="pass">
<el-input
type="password"
v-model="ruleForm.pass"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input
type="password"
v-model="ruleForm.checkPass"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model.number="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<!-- <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button> -->
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
ruleForm: {
type: Object,
default: {
pass: "",
checkPass: "",
age: "",
},
},
},
data() {
var checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error("年龄不能为空"));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error("请输入数字值"));
} else {
if (value < 18) {
callback(new Error("必须年满18岁"));
} else {
callback();
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入密码"));
} else {
if (this.ruleForm.checkPass !== "") {
this.$refs.ruleForm.validateField("checkPass");
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"));
} else if (value !== this.ruleForm.pass) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
};
return {
// ruleForm: {
// pass: '',
// checkPass: '',
// age: ''
// },
rules: {
pass: [{ validator: validatePass, trigger: "blur" }],
checkPass: [{ validator: validatePass2, trigger: "blur" }],
age: [{ validator: checkAge, trigger: "blur" }],
},
};
},
methods: {
async submitForm(formName) {
try {
const flag = await this.$refs[formName].validate();
return true;
} catch (error) {
this.$message.error("请填写表单信息");
return false;
}
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
// 清除
clearValidate() {
this.$refs["ruleForm"].clearValidate();
},
},
deactivated() {
this.$emit("DeactiveOneData", this.ruleForm);
},
activated() {
this.clearValidate();
},
};
</script>
<style>
</style>
form2.vue
<template>
<div class="form2" key="form2">
<el-form
:model="form"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-form"
>
<el-form-item label="活动名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动区域" prop="regionActive" >
<el-select v-model="form.regionActive" placeholder="请选择活动区域" >
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间" required>
<el-col :span="11">
<el-form-item prop="date1">
<el-date-picker
type="date"
placeholder="选择日期"
v-model="form.date1"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-form-item prop="date2">
<el-time-picker
placeholder="选择时间"
v-model="form.date2"
style="width: 100%"
></el-time-picker>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="即时配送" prop="delivery">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="活动性质" prop="type">
<el-checkbox-group v-model="form.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊资源" prop="resource">
<el-radio-group v-model="form.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动形式" prop="desc">
<el-input type="textarea" v-model="form.desc"></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
form: {
type: Object,
default: {
name: "",
regionActive: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: "",
},
},
},
data() {
return {
// form: {
// name: "",
// regionActive: "",
// date1: "",
// date2: "",
// delivery: false,
// type: [],
// resource: "",
// desc: "",
// },
rules: {
name: [
{ required: true, message: "请输入活动名称", trigger: "blur" },
{ min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" },
],
regionActive: [
{ required: true, message: "请选择活动区域", trigger: "change" },
],
date1: [
{
type: "date",
required: true,
message: "请选择日期",
trigger: "change",
},
],
date2: [
{
type: "date",
required: true,
message: "请选择时间",
trigger: "change",
},
],
type: [
{
type: "array",
required: true,
message: "请至少选择一个活动性质",
trigger: "change",
},
],
resource: [
{ required: true, message: "请选择活动资源", trigger: "change" },
],
desc: [{ required: true, message: "请填写活动形式", trigger: "blur" }],
},
};
},
activated() {
this.clearValidate()
},
mounted() {
this.clearValidate()
},
methods: {
// 提交验证
async submitForm(formName) {
try {
const flag = await this.$refs[formName].validate();
return true;
} catch (error) {
this.$message.error("请填写表单信息");
return false;
}
},
// 清除
clearValidate() {
this.$refs['ruleForm'].clearValidate();
}
},
deactivated() {
this.$emit("DeactiveOneData", this.form);
},
};
</script>
<style>
</style>
form3.vue
<template>
<div class="form1">
<el-form ref="ruleForm" :rules="rules" :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="审批人" prop="user">
<el-input v-model="formInline.user" placeholder="审批人"></el-input>
</el-form-item>
<el-form-item label="活动区域" key="form3">
<el-select v-model="formInline.region" placeholder="活动区域" >
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<!-- <el-button type="primary" @click="onSubmit">查询</el-button> -->
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: {
formInline: {
type: Object,
default: {
user: "",
region: "",
},
},
},
data() {
return {
// formInline: {
// user: "",
// region: "",
// },
rules:{
user: [ { required: true, message: "请输入审批人", trigger: "blur" }],
}
};
},
mounted() {
this.clearValidate()
},
activated() {
this.clearValidate()
},
methods: {
async submitForm(formName) {
try {
const flag = await this.$refs[formName].validate();
return true;
} catch (error) {
this.$message.error("请填写表单信息");
return false;
}
},
// 清除
clearValidate() {
this.$refs['ruleForm'].clearValidate();
}
},
};
</script>
<style>
</style>
这里最终效果跟1一样,只不过这是每个组件里面有方法
总结:每一步一提交适合组件切换,简单的最后一块提交的使用一个页面form用v-if(公共部分也可抽出封装)
|