场景:采用工el-select方式搜索企业下的用户,并且采用多选的方式,选中的选项可回显展示在输入框中,且下拉选项需要带上checkbox方式。
el-select提供了远程搜索和多选功能,但选项中需要自定义添加el-checkbox方式,但由于点击选项后自动会触发change事件,且添加后的选项点击删除,选择框不能对应删除,所以需要禁用el-select点击选项后的事件,采用@click.stop的方式,且在样式上将选项的长度延伸至100%。防止点击其他空白触发事件。
为了统一格式,在回显时赋值的数据和绑定的数据格式需要统一,采用{accountId, loginName}的方式,其中buildItem方法,以及handleChange中都有所体现。
接下来又发现无法回显tag数据,这是因为采用了远程搜索的方式,选择器没有选项,无法对应匹配内容,也就导致输入框中的tag无法回显。可采用以下解决方法:
源码中是利用cachedOptions方法将当前的下拉选项隐匿储存的集合,我们可以通过在这个集合中把我们需要显示的选项添加进去。
其中selectedList为需要回显的原始数据,selectedAccount为处理后需要回显的数据,selectDom为选择器dom。
主要代码如下:
<el-select
ref="selectDom"
v-model="selectedAccount"
multiple
remote
filterable
placeholder="请输入"
:remote-method="searchOptions"
:loading="loading"
popper-class="select-account"
value-key="accountId"
>
<el-option
v-for="item in options"
:key="item.accountId"
:label="item.loginName"
:value="buildItem(item)"
>
<p @click.stop class="check-option">
<el-checkbox
:value="
selectedAccount.filter((it) => it.accountId == item.accountId)
.length > 0
"
:key="item.accountId"
@change="
handleChange($event, `${item.accountId},${item.loginName}`)
"
>{{ item.loginName }}</el-checkbox
>
</p>
</el-option>
</el-select>
watch: {
selectedList: {
handler(val) {
if (val && val.length) {
//解决远程搜索分页导致无法回显tag问题
this.$nextTick(() => {
val.forEach((item) => {
this.selectedAccount.push({
accountId: item.accountId,
loginName: item.loginName
})
this.$refs.selectDom.cachedOptions.push({
currentLabel: item.loginName,
currentValue: {
accountId: item.accountId,
loginName: item.loginName
},
label: item.loginName,
value: {
accountId: item.accountId,
loginName: item.loginName
}
})
})
})
}
}
}
},
methods: {
async getSelectOptions() {
//远程搜索
this.options = xxxx
},
buildItem(item) {
return {
accountId: item.accountId,
loginName: item.loginName
}
},
handleChange(check, val) {
if (!val) return
let accountId = val.split(',')[0]
let loginName = val.split(',')[1]
//check为true表示选中则添加,为false表示不选中则删除
if (check) {
this.selectedAccount.push({
accountId,
loginName
})
} else {
this.selectedAccount = this.selectedAccount.filter(
(item) => item.accountId !== accountId
)
}
},
searchOptions(val) {
if (val) {
this.searchVal = val
this.getSelectOptions()
}
}
}
<style lang="less">
.select-account {
li {
padding: 0 !important;
.check-option {
padding: 0 8px;
}
label {
width: 100%;
}
&:after {
display: none;
}
}
}
</style>