The encapsulation of the all-select method of el-select of element-plus.
origin:
The project is built with vue3+elmentui-plus +ts. The user interface design requires a drop-down selection box with select all. However, the drop-down multi-select box provided by the official website of element plus
has no button for selecting all in this form, and the style does not conform to the expected operation of selecting all. So I started to think of ways to combine a new condition to encapsulate a new component.
Show results:
Design principle:
Since users are more keen on the drop-down box with full selection, and don’t like the √ selection mark on the right, they need to replace it with the same selection box as the multi-selection box, so, according to the existing conditions, I use el-select + el-checkbox form to write this component.
Component code composition creates a subcomponent selectCheckBox.vue file
html part
<el-select
v-model="menusTitle"
multiple
collapse-tags
collapse-tags-tooltip
:placeholder="props.placeholder"
clearable
@clear="clearData"
>
<!-- @change="changeSelectMenu" -->
<el-checkbox v-model="checkedAll" @change="selectAll">全选</el-checkbox>
<el-option
v-for="(item, index) in menuList"
:key="item[props.id]"
:value="item[props.id]"
>
<el-checkbox
:label="item[props.label]"
size="large"
@change="changeCheckBox(item, index)"
:checked="isChecked(item, index)"
v-model="checkBoxObj[index]"
/>
</el-option>
</el-select>
js part
<script lang="ts" setup>
import { ref, reactive, defineProps, defineEmits } from "vue";
const props = defineProps({
list: { type: Array, required: true },
id: { type: String, required: true },
label: { type: String, required: true },
modelValue: { type: Array },
placeholder: { type: String, default: "选择" },
});
const emit = defineEmits(["update:modelValue"]);
const value = ref("");
const checkedAll = ref("false");
const menus = ref([]);
const menuList = props.list;
const checkBoxObj = ref({});
menuList.forEach((res, index) => {
checkBoxObj.value[index] = false;
});
const menusTitle = ref([]);
const changeSelectMenu = (val) => {};
const selectAll = (value) => {
menus.value = [];
menusTitle.value = [];
if (value) {
menuList.forEach((item, index) => {
menus.value.push(item[props.id]);
menusTitle.value.push(item[props.label]);
checkBoxObj.value[index] = true;
});
} else {
menus.value = [];
menusTitle.value = [];
menuList.forEach((item, index) => {
checkBoxObj.value[index] = false;
});
}
emit("update:modelValue", menus.value);
};
const isChecked = (item) => {
return menus.value.indexOf(item[props.id]) > -1;
};
const changeCheckBox = (item, index) => {
let i = menus.value.indexOf(item[props.id]);
if (i == -1) {
menus.value.push(item[props.id]);
menusTitle.value.push(item[props.label]);
} else {
menus.value.splice(i, 1);
menusTitle.value.splice(i, 1);
}
if (menus.value.length == menuList.length) {
checkedAll.value = true;
} else {
checkedAll.value = false;
}
emit("update:modelValue", menus.value);
};
const clearData = () => {
menus.value = [];
menusTitle.value = [];
emit("update:modelValue", menus.value);
checkedAll.value = false;
menuList.forEach((item, index) => {
checkBoxObj.value[index] = false;
});
};
</script>
css part:
<style lang="scss" scoped>
.el-select-dropdown {
.el-checkbox {
display: flex;
align-items: center;
padding-left: 20px;
width: 100%;
box-sizing: border-box;
}
.el-select-dropdown__item {
// background-color: red !important;
padding: 0;
display: flex;
align-items: center;
}
}
</style>
parent component call
html import part
<selectCheckBox
v-model="value3 "
:list="options"
id="value"
label="label"
placeholder="选择项目"
></selectCheckBox>
js import part
import selectCheckBox from "@_components/dataClassification/selectCheckBox.vue";
const value3 = ref([]);
const options = [
{
value: "1",
label: "项目一",
},
{
value: "2",
label: "项目二",
},
{
value: "3",
label: "项目三",
},
];
Summarize
The component is still in the process of upgrading, and the secondary packaging component is processed. The goal of the further encapsulation process is to make a parameter component of the class el-select. Keep it for the record today.