自定义实现一个搜索选择弹窗,至少选择一项。
效果图:
组件代码:
<template>
<el-dialog
ref="dialog-zb"
:key="title"
v-dialogDrag
:visible.sync="visible"
:width="width"
:modal-append-to-body="modalAppendToBody"
:append-to-body="appendToBody"
:before-close="handleDialogCloseIn">
<span slot="title" class="el-dialog__title">
<label>
{{ this.title }}(
<label style="color: cornflowerblue">
请选择
{{ this.resultNum }}
项内容
</label>
)
</label>
</span>
<el-form :model="queryModel" label-width="120px" style="align-content: center">
<el-row type="flex" style="padding:5px;">
<slot name="queryFormItem">
</slot>
<el-form-item>
<el-button
id="btnQuery"
type="primary"
icon="el-icon-search"
@click="handleBtnQueryClick"
>查询</el-button>
</el-form-item>
</el-row>
</el-form>
<el-table
ref="multipleTable-zb"
v-loading="queryLoading"
:data="tableData"
element-loading-text="Loading"
element-loading-background="rgba(0, 0, 0, 0.5)"
element-loading-spinner="el-icon-loading"
fit
highlight-current-row
border
stripe
height="500"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
align="center"
>
<slot name="tableColumn" />
</el-table>
<span slot="footer" class="dialog-footer">
<el-button @click="onBtnCancelClick">取 消</el-button>
<el-button type="primary" :disabled="nowSelections.length !== resultNum" @click="onBtnSaveClick">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: 'SearchSelectorDialog',
model: {
prop: 'visible',
event: 'change'
},
props: {
// dialog描述
title: { type: String, default: '数据查询选择器' },
// dialog可见性
visible: { type: Boolean, required: true, default: true },
// dialog宽度
width: { type: String, default: '40%' },
// 能否关闭dialog
canClose: { type: Boolean, default: false },
// 查询模型
queryModel: { type: Object, default: null },
// 默认input Model
// eslint-disable-next-line vue/require-default-prop
defaultInputModel: Object,
// 表格数据
tableData: { type: Array, required: true },
// 选取结果数
resultNum: { type: Number, required: true, default: 1 },
// 加载
queryLoading: { type: Boolean, default: false },
// 结果
results: { type: Array, default: null },
modalAppendToBody: Boolean,
appendToBody: Boolean
},
data() {
return {
nowSelections: [],
lastSelections: []
}
},
watch: {
visible(val) {
if (val) {
this.handleDialogShow()
}
}
},
methods: {
/**
* @description: 取消的时候回调外部时间
* @param {*}
* @return {*}
*/
onBtnCancelClick() {
this.$emit('CancelClick', this)
if (this.canClose === true) {
this.handleDialogClose()
}
},
onBtnSaveClick() {
// 传参数给父组件,选中的值
this.results = this.nowSelections
this.$emit('OkButtonClick', this.nowSelections) // 回调父组件的时间具体业务逻辑由父组件实现
if (this.canClose === true) {
this.handleDialogClose()
}
},
handleDialogCloseIn: function(dialog) {
this.$emit('CancelClick', this)
if (this.canClose === true) {
this.handleDialogClose()
}
},
/**
* 只要dialog关闭就会调用
*/
beforeDialogClose: function() {
this.$emit('beforeDialogClose', this)
},
afterDialogClose: function() {
this.$emit('afterDialogClose', this)
},
handleDialogClose: function() {
this.beforeDialogClose()
// eslint-disable-next-line no-unused-vars
const dialog = this.$refs['dialog-zb']
dialog.hide(true)
this.$emit('visibleChange', false)
this.afterDialogClose()
this.$emit('handleDialogClose', this)
},
handleDialogShow: function() {
this.queryLoading = true
this.$emit('handleDialogShow', this)
this.queryLoading = false
},
/**
* 以下是查询部分
*/
handleBtnQueryClick: function() {
this.queryLoading = true
this.$emit('handleButtonQueryClick', this.queryModel)
this.queryLoading = false
},
/**
* 表选择
*/
handleSelectionChange: function(selections) {
if (selections.length > this.resultNum) {
this.$message.info('只能选取' + this.resultNum + '项内容')
const table = this.$refs['multipleTable-zb']
table.clearSelection()
this.lastSelections.forEach(
(item) => {
table.toggleRowSelection(item, true)
}
)
} else {
this.lastSelections = this.nowSelections
this.nowSelections = selections
}
},
handleRowClick: function(row) {
let dumpling = false
this.nowSelections.forEach(item => {
// 点击的行已选,取消选中
if (this.isObjectValueEqual(row, item)) {
dumpling = true
}
})
if (dumpling) {
this.$refs['multipleTable-zb'].toggleRowSelection(row, false)
return
}
if (this.nowSelections.length < this.resultNum) {
this.$refs['multipleTable-zb'].toggleRowSelection(row, true)
} else {
this.$message.info('只能选取' + this.resultNum + '项内容')
}
},
isObjectValueEqual(a, b) {
// 取对象a和b的属性名
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
// 判断属性名的length是否一致
if (aProps.length !== bProps.length) {
return false
}
// 循环取出属性名,再判断属性值是否一致
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i]
if (a[propName] !== b[propName]) {
return false
}
}
return true
}
}
}
</script>
<style scoped>
</style>
使用
import组件
<search-selector-dialog
:key="searchSelectorDialogType"
v-model="searchSelectorDialogVisible"
:table-data="searchSelectorDialogTableData"
:result-num="1"
:query-model="searchSelectorDialogKeyword"
:title="searchSelectorDialogTitle"
:query-loding="searchSelectorDialogQueryLoading"
can-close
@handleDialogClose="handleDialogClose"
@beforeDialogClose="beforeDialogClose"
@handleButtonQueryClick="handleButtonQueryClick"
@OkButtonClick="onOkButtonClick"
@CancelClick="onCancelClick"
@afterDialogClose="afterDialogClose"
>
<el-form-item label="" slot="queryFormItem">
<el-input v-model="searchSelectorDialogKeyword" style="width: 150px" placeholder="输入查询关键词" />
</el-form-item>
<el-table-column slot="tableColumn" align="center" width="50" type="selection" />
<el-table-column slot="tableColumn" align="center" prop="name" label="名称" width="200"/>
<el-table-column slot="tableColumn" align="center" prop="address" label="地址" width="400" />
</search-selector-dialog>