【Vue】可编辑表格与三级联动下拉
需求是给员工分配岗位,设计上是一人多岗的存在...
单位 —— 部门 —— 岗位 这样的层级
功能效果:
因为员工可以在不同的单位下任职岗位,所以这个每一个岗位都是一个独立
查询单位列表是固定的,但是每个单位下的部门不是固定的,每个单位下的部门下的岗位也是不一样的
每一行的下拉列表都是独立维护的
这种表格是和表单在一起的,所以存储逻辑是,直接清空以前的记录,根据提交的这份重新写库保存
可编辑表格的校验还是可以通过Form表单校验,TableData放在form表单对象里面
校验的prop属性是关联TableData的下标元素属性这样实现的,rules校验对象也是单独设置
注意下拉列表引用的集合都是下标元素里的(如果不是这样的联动列表,可以共用...)
<template>
<div>
<el-form :ref="formRef" :model="form" :rules="rules" label-width="135px" :inline="true" label-position="top" size="small">
<div class="location2">
<span style="font-weight: bolder">{{ form.emName + ' ' + form.emPhone }}</span>
<span>
<svg-icon icon-class="tj-icon" class="tj-icon" style="margin-right: 10px" @click="newEditRow" />
<svg-icon icon-class="sc-icon" class="tj-icon" @click="deleteEditRow" />
</span>
</div> <div>
<el-table :ref="editableTableRef" v-loading="loading" size="small" stripe highlight-current-row :data="form.tableData" :row-class-name="rowClassName" :row-style="rowStyle" @row-click="rowClick" @selection-change="handleSelectionChange">
<el-table-column align="center" type="index" width="50px" label="序号" />
<el-table-column prop="sysArCoId" min-width="160px" align="left" label="所属公司">
<template slot-scope="sc">
<el-form-item size="mini" :prop=" `tableData.${sc.$index}.sysArCoId` " :rules="rules.sysArCoId" :style="inputStyle">
<el-select v-model="sc.row.sysArCoId" :style="inputStyle" clearable placeholder="请选择" @change="selectCorpChange(sc.$index, sc.row)">
<el-option v-for="item in sc.row.corpList" :key="item.id" :label="item.coName" :value="item.id" />
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="sysArDeId" min-width="160px" align="left" label="所属部门">
<template slot-scope="sc">
<el-form-item size="mini" :prop=" `tableData.${sc.$index}.sysArDeId` " :rules="rules.sysArDeId" :style="inputStyle">
<el-select v-model="sc.row.sysArDeId" :style="inputStyle" clearable placeholder="请先选择所属公司" @change="selectDeptChange(sc.$index, sc.row)">
<el-option v-for="item in sc.row.deptList" :key="item.sysArDeId" :label="item.deName" :value="item.sysArDeId" />
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="poName" min-width="160px" align="left" label="岗位名称">
<template slot-scope="sc">
<el-form-item size="mini" :prop=" `tableData.${sc.$index}.sysArPoId` " :rules="rules.sysArPoId" :style="inputStyle">
<el-select v-model="sc.row.sysArPoId" :style="inputStyle" clearable placeholder="请先选择所属部门">
<el-option v-for="item in sc.row.postList" :key="item.id" :label="item.poName" :value="item.id" />
</el-select>
</el-form-item>
</template>
</el-table-column>
</el-table>
</div>
</el-form> <div class="drawer-bottom-bar">
<el-button type="primary" @click="submit">确定</el-button>
<el-button @click="closeEditDialog">取消</el-button>
</div>
</div>
</template>
Data属性和Prop属性:
查询这个列表的接口还是需要的,直接用翻页接口,就不要翻页组件,size变量直接写死999,足够展示了
单位列表是共用的,加载一次就可以给每一行用
props: {
form: {
type: Object,
required: true,
default() {
return {
tableData: []
}
}
}
},
data() {
return {
/* 列表变量 */
loading: false,
page: {
current: 0,
size: 999,
total: 0
}, /* 表单变量 */
formRef: 'currentRowRefKey',
editableTableRef: 'editableTableRefKey',
rules: {
sysArCoId: [
{ required: true, message: '请选择所属公司', trigger: 'change' }
],
sysArDeId: [
{ required: true, message: '请选择所属部门', trigger: 'change' }
],
sysArPoId: [
{ required: true, message: '请选择岗位名称', trigger: 'change' }
]
},
commonStyle: { width: '47%' },
inputStyle: { width: '100%' },
isUpdate: false,
selectionRow: [],
corpList: []
}
}
Method方法区内容:
一、解决新增操作时的问题
1、newEditRow 创建一条新行时,直接push这个行对象,这里初始化关联的员工ID和单位列表
2、deleteEditRow 删除编辑行,(用Splice方法跟据选中的下标来删除即可)这里用的是非复选框实现的选中方式 参考文章:http://www.javashuo.com/article/p-fbtbpqzn-bc.html
3、selectCorpChange 监听单位下拉事件,清空所有下级列表和选中的值,根据单位ID重新加载部门列表
4、selectDeptChange 监听部门下拉事件,同理
二、解决回显和编辑操作的问题
query 在加载列表的时候,同步阻塞执行加载方法把对应的列表放到行中
这里要注意的问题就是 异步执行顺序,一定要先等待单位列表加载完了,才能加载整个岗位的查询
methods: {
newEditRow() {
const row = {
sysArEmId: this.form.id,
sysArCoId: '',
sysArPoId: '',
sysArDeId: '',
corpList: [... this.corpList],
deptList: [],
postList: []
}
this.form.tableData.push(row)
},
deleteEditRow() {
const selectedLength = this.selectionRow.length
const totalLength = this.form.tableData.length
if (totalLength === 0) return this.$message.error('没有编辑行了')
if (selectedLength > 0) {
for (let i = selectedLength - 1; i >= 0; i--) {
this.form.tableData.splice(this.selectionRow[i].rowIndex, 1)
}
} else {
const lastOne = totalLength - 1
this.form.tableData.splice(lastOne, 1)
}
this.$refs[this.editableTableRef].clearSelection()
this.selectionRow = []
},
selectCorpChange(rowIdx, row) {
this.form.tableData[rowIdx].sysArDeId = ''
this.form.tableData[rowIdx].sysArPoId = ''
if (!row.sysArCoId) {
this.form.tableData[rowIdx].deptList = []
this.form.tableData[rowIdx].postList = []
}
this.loadDeptList(row.sysArCoId, rowIdx)
},
selectDeptChange(rowIdx, row) {
this.form.tableData[rowIdx].sysArPoId = ''
if (!row.sysArDeId) this.form.tableData[rowIdx].postList = []
this.loadPostList(row.sysArDeId, rowIdx)
},
async initialCorpList() {
const param = {}
const { data: res } = await getCompanyList(param)
this.corpList = res
},
async loadDeptList(val, rowIdx) {
const param = { sysArCoId: val }
const { data: res } = await getAllocatedDepartmentList(param)
this.form.tableData[rowIdx].deptList = res
},
async loadPostList(val, rowIdx) {
const param = { sysArDeId: val }
const { data: res } = await getSysArPostList(param)
this.form.tableData[rowIdx].postList = res
},
handleSizeChange(pageSize) {
this.page.size = pageSize
this.query()
},
handleCurrentChange(pageIndex) {
this.page.current = pageIndex
this.query()
},
searchPage() {
this.page.current = 0
this.page.total = 0
this.query()
},
async query() {
this.loading = true
const param = {
sysArEmId: this.form.id,
page: this.page
}
const { data: res, total } = await getEmployeePositionPage(param)
for (let i = 0; i < res.length; i++) {
res[i].corpList = [... this.corpList]
const { data: deptList } = await getAllocatedDepartmentList({ sysArCoId: res[i].sysArCoId })
res[i].deptList = deptList
const { data: postList } = await getSysArPostList({ sysArDeId: res[i].sysArDeId })
res[i].postList = postList
}
this.form.tableData = res
this.page.total = total
this.loading = false
},
closeEditDialog() {
this.$parent.$parent.closePostAssignDialog()
},
submit() {
this.$refs[this.formRef].validate(async valid => {
if (!valid) return
this.form.empoList = this.form.tableData
await assignEmployeePosition(this.form)
this.$message.success('分配任岗成功')
})
}
}
Created的执行:
created() {
this.initialCorpList().then(() => { this.searchPage() })
}
多个表格,拆分校验的问题:
例如下图这样,存在明细表和行程信息表,可以在一个实例的表单对象上面写
如果表格已经是拆分成其他组件来写的话,再花时间合并到一个文件中就很费劲
把可编辑表格按组件引入进来
key用来刷新组件
ref用来获取组件的属性
keyId是传递外键
在提交表单的时候,可以拆分两个Promise对象进行处理
执行每个表单的校验,通过则resolve,反之reject
在最后放入All方法按顺序执行,只有都通过校验,才会进入then方法执行提交
不要忘记把可编辑表格的数据放入提交的表单中
所以,后面存在若干个表格,依次类推实现
submit() {
const part1Validate = new Promise((resolve, reject) => {
this.$refs[this.formRef].validate(async valid => {
if (valid) resolve()
else reject()
})
}) const part2Validate = new Promise((resolve, reject) => {
const formTable = this.$refs['detailList'].$refs['currentRowRefKey']
formTable.validate(valid => {
if (valid) resolve()
else reject()
})
}) Promise.all([part1Validate, part2Validate]).then(async() => {
this.form.detailList = this.$refs['detailList'].form.tableData
if (this.isUpdate) {
await updateFinSpApply(this.form)
this.$message.success('更新成功')
this.$parent.$parent.searchPage()
} else {
const { data: res } = await addFinSpApply(this.form)
this.isUpdate = !!res
if (this.isUpdate) {
this.form.id = res.id
this.freshFlag = new Date().getTime() /* 刷新子组件的key属性,让子组件重新加载 */
this.$message.success('新增成功')
}
this.$parent.$parent.searchPage()
}
})
}
【Vue】可编辑表格与三级联动下拉的更多相关文章
- PHP用ajia代码写三级联动下拉
下面是我做三级联动下拉的步骤以及逻辑 第一步:先做一个省市区表格 第二步:建个PHP页面显示用我是在<body>里放<div>用来接收要显示的省市区表格信息,里面嵌入jquer ...
- 项目总结01:JSP mysql SpringMvc下中国省市县三级联动下拉框
JSP mysql SpringMvc下中国省市县三级联动下拉框 关键词 JSP mysql数据库 SpringMvc ajax Controller层 Service层 中国地区 省 ...
- Android实现三级联动下拉框 下拉列表spinner
Android实现(省.市.县)三级联动下拉框 下拉列表spinner 转载请注明出处: http://www.goteny.com/articles/2013/11/46.html http://w ...
- Web 1三级联动 下拉框 2添加修改删除 弹框
Web 三级联动 下拉框 using System; using System.Collections.Generic; using System.Linq; using System.Web; u ...
- JS年月日三级联动下拉框日期选择代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- jquery+html三级联动下拉框
jquery+html三级联动下拉框及详情页面加载时的select初始化问题 html写的三个下拉框,如下: <select name="ddlQYWZYJ" id=&q ...
- jquery+ligerform三级联动下拉框
如下为ligerform里的三级联动下拉框: var formData=[ {display:,width:,space:,type:"select",group:"区域 ...
- 用jsp实现省市区三级联动下拉
jsp+jquery实现省市区三级联动下拉 不少系统都需要实现省市区三级联动下拉,像人口信息管理.电子商务网站.会员管理等,都需要填写地址相关信息.而用ajax实现的无刷新省市区三级联动下拉则可以改善 ...
- JQ与AJAX 省市区三级联动下拉框
用于初学者学习基本的联动下拉框,废话不多说,见代码 首先看控制器里的3个下拉框对应代码: public ActionResult GetProvinceList() { ProvinceReposit ...
- php+ajax的三级联动下拉菜单
封装一个三级联动,就可以在任何页面进行引用了 先写个页面引用一下这个js <head> <meta http-equiv="Content-Type" conte ...
随机推荐
- ts interface
在TypeScript中,接口(interface)用于定义对象的结构,可以描述对象的属性.方法等.下面是一个简单的例子,演示如何使用 TypeScript 接口: // 定义一个接口表示一个人的信息 ...
- 小米 红米 Redmi 屏幕录制默认参数设置
小米 红米 Redmi 屏幕录制默认参数设置 视频画质:16Mbps. 帧数:60fps.
- nordic—RTC+PPI定时驱动某外设做非单次触发(本次测试为驱动GPIO口做电平翻转)
简介:在nordic的开发中使用到RTC时,对于比较通道0/1/2/3的中断来说,如果不进行相关配置(如SDK中例子,使用的RTC比较通道就只能触发一次,不能多次触发),会导致比较中断只进入一次,如果 ...
- 如何使用JavaScript实现在线Excel附件的上传与下载?
前言 在本地使用Excel时,经常会有需要在Excel中添加一些附件文件的需求,例如在Excel中附带一些Word,CAD图等等.同样的,类比到Web端,现在很多人用的在线Excel是否也可以像本地一 ...
- Mybatis.xml文件中 大于小于等于
Mybatis中 大于小于等于的转义写法第一种写法:符号 转义字符< <<= <=> >>= >=& &am ...
- jqurey基础知识和常用事件方法
样式文件不需要<style>标签 引用style文件的方法 <link href="main.css" rel="stylesheet" st ...
- CodeForces 1935A
题目链接:Entertainment in MAC 思路 当当前操作次数n为偶数时,若原字符串大于反转字符串则可以将原字符串反转n - 2次,则得到的还是原字符串,此时反转一次,并将其再次反转的字符串 ...
- 教您在79元ARM平台实现H.265视频解码
什么是H.265视频编解码? (1)什么是H.265 H.265,也被称为HEVC(HighEfficiency Video Coding),作为H.264的继任者,提供了更好的视频压缩和更高的视频质 ...
- NXP i.MX 8M Mini视频开发案例分享 (上)
本文主要介绍i.MX 8M Mini的视频开发案例,包含基于GStreamer的视频采集.编解码.算法处理.显示以及存储案例,GigE工业相机测试说明,H.265视频硬件解码功能演示说明等. 注:本案 ...
- PO、VO、BO、DTO、POJO、DAO、DO
DO: domain object持久对象就是从现实世界中抽象出来的有形或无形的业务实体. PO:persistant object持久对象最形象的理解就是一个PO就是数据库中的一条记录.好处是可以把 ...