一. 页面需求
在页面上,我需要从多个数据源选择一些数据保存,觉得用穿梭框比较方便,但是element的transfer好像针对单个数据源,并且个人觉得外观上也比较。。所以决定用两个el-table来改造一个穿梭框。页面框架大致分为两个区域:数据候选区、确认区。
数据候选区:通过按钮获取后端数据传入到候选区
数据确认区: 勾选候选区的数据后,实时更新到确认区,最后保存的数据为确认区中勾选的数据
二. 前端代码
数据选中与否的识别是通过唯一的 id,所以下面代码只展示 id。
1. 数据候选区
<div style="height: 30px; border: 1px solid #f5eeee">
<span style="font-weight: bold;">候选区</span>
</div>
<el-table ref="temp" :data="tableData" height="500" style="width: 100%"
border
@select="toggleSelect1"
@select-all="selectAll1">
<el-table-column type="selection"></el-table-column>
<el-table-column prop="id" label="id"></el-table-column>
</el-table>
2. 数据确认区
<div style="height: 30px; border: 1px solid #f5eeee">
<span style="font-weight: bold;">最终确认区</span>
</div>
<el-table ref="last" :data="lastData" height="500" style="width: 100%"
border
@selection-change="handleSelectionChange"
@select="toggleSelect2"
@select-all="selectAll2">
<el-table-column type="selection"></el-table-column>
<el-table-column prop="id" label="id"></el-table-column>
</el-table>
3. JS 代码
通过绑定两个表格的checkbox事件,来实现内容穿梭。
// 候选区单行的checkbox点击事件
toggleSelect1(selection, row) {
if (selection.indexOf(row) >= 0) {
if (this.lastData.map((v) => v.id).indexOf(row.id) < 0) {
this.lastData.push(row);
this.$refs.last.toggleRowSelection(row, true);
} else {
var srow = this.lastData.filter((v) => { return v.id == row.id });
this.$refs.last.toggleRowSelection(srow[0], true);
}
} else {
if (this.lastData.map((v) => v.id).indexOf(row.id) >= 0) {
var srow = this.lastData.filter((v) => { return v.id == row.id });
this.$refs.last.toggleRowSelection(srow[0], false);
}
}
},
// 确认区单行的checkbox点击事件
toggleSelect2(selection, row) {
if (selection.indexOf(row) >= 0) {
if (this.tableData.map((v) => v.id).indexOf(row.id) >= 0) {
var srow = this.tableData.filter((v) => { return v.id == row.id });
this.$refs.temp.toggleRowSelection(srow[0], true);
}
} else {
if (this.tableData.map((v) => v.id).indexOf(row.id) >= 0) {
var srow = this.tableData.filter((v) => { return v.id == row.id });
this.$refs.temp.toggleRowSelection(srow[0], false);
}
}
},
// 候选区全选的checkbox点击事件
selectAll1(selection) {
if (selection.length == 0) {
var idlist = this.tableData.map((v) => v.id);
var srow = this.lastData.filter((v) => { return idlist.indexOf(v.id) >= 0 });
if (srow) {
srow.forEach((row) => {
this.$refs.last.toggleRowSelection(row, false);
})
}
} else {
var idlist = this.lastData.map((v) => v.id);
selection.forEach((row) => {
if (idlist.indexOf(row.id) < 0) {
this.lastData.push(row);
}
this.$refs.last.toggleRowSelection(row, true);
})
}
},
// 确认区全选的checkbox点击事件
selectAll2(selection) {
var idlist = this.lastData.map((v) => v.id);
var srow = this.tableData.filter((v) => { return idlist.indexOf(v.id) >= 0 });
if (srow) {
if (selection.length == 0) {
srow.forEach((row) => {
this.$refs.temp.toggleRowSelection(row, false);
})
}else{
srow.forEach((row) => {
this.$refs.temp.toggleRowSelection(row, true);
})
}
}
},
// 获取确认区勾选的数据
handleSelectionChange(selection) {
this.savedata= selection;
this.selectIdList = selection.map((v)=>v.id); // 选中的id列表
},
4. 异步数据切换数据源
axios.get('127.0.0.1/my_request.php').then((res) => {
this.tableData = res.data.data;
// 如果新数据源有数据在确认区已被选中,需在候选区默认也选中
var rows = this.tableData.filter((v) => {
return this.selectIdList.includes(v.id)
});
this.$nextTick(() => {
rows.forEach((row) => {
this.$refs.temp.toggleRowSelection(row, true);
})
})
}).catch(() => { });
5. 不可选数据
如果数据源中有一些数据不可供选择,第一种方法是在后端筛除,第二种方法是传回前端,但要能识别哪些id不可选择。例如识别出的 id 存在 this.disableIDList 中。接下来在数据候选区的selction列中绑定selectable方法,来确定哪些行可选。
<el-table-column type="selection" :selectable="selectable"></el-table-column>
computed: {
selectable: function () {
return (row, index) => {
if (this.disableIDList.indexOf(row.id) >= 0) {
return false;
} else {
return true
}
}
},
},