In the process of a project development, components similar to Cascader were needed, but the cascading selector was arranged horizontally, and the STYLE given by UI was arranged vertically (as shown below). Therefore, element’s Tree and Select components were used for secondary packaging. Implements the following functions to support single and multiple tree selection

Implementation code:

<div class="my-select">
    <el-select :value="value" :multiple="multiple" placeholder="Please select" @remove-tag="removeTag"
               :clearable="clearable" @clear="clearHandle">
        <el-option :value="value">
            <el-tree
              id="tree-option"
              ref="selectTree"
              :accordion="accordion"
              :data="treeData"
              :props="defaultProps"
              show-checkbox
              :expand-on-click-node="false"
              :node-key="defaultProps.value"
              :check-strictly="true"
              @check="handleNodeClick"
              @check-change="handleCheckChange"
            ></el-tree>
        </el-option>
    </el-select>
</div>
Copy the code
// Style changes.my-select {
    //display: flex;
    //flex-direction: column;
    //align-items: center;
}

.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
    height: auto;
    padding: 0;
    overflow: hidden;
    overflow-y: auto;
}

.el-select-dropdown__item.selected {
    font-weight: normal;
}

ul li >>> .el-tree .el-tree-node__content {
    height: auto;
    padding: 0 20px;
}

.el-tree-node__label {
    font-weight: normal;
}

.el-tree >>> .is-current .el-tree-node__label {
    color: #409eff;
    font-weight: 700;
}

.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {
    color: # 606266;
    font-weight: normal;
}

/deep/ .el-select {
    width: 100% ! important;
}
Copy the code

To implement this, define props and accept parameters passed from the parent component

props: {
    /* Configuration options */
    defaultProps: {
        type: Object.default: () = > {
            return {
                value: "id".// ID field name
                label: "label".// Display the name
                children: 'children' // Subfield name}}},/* Display data */
    treeData: {
        type: Array.default: () = >[]},/* Can clear options */
    clearable: {
        type: Boolean.default: () = > true
    },
    /* Automatically fold */
    accordion: {
        type: Boolean.default: () = > true
    },
    /* Optional initial value */
    radioValue: {
        type: String.default: () = > ' '
    },
    /* Multiple initial values */
    multipleValues: {
        type: Array.default: () = >[]},/* Select */
    multiple: {
        type: Boolean.default: () = > true}}Copy the code

Determine whether multiple or single options are available when initializing the loading component

mounted() {
    // If the parent passes a multiple value of true, it is a single component. If the parent passes a multiple value, it calls the corresponding method to initialize the default data
    this.multiple ? this.radioInit() : this.multipleInit();
}
Copy the code

Next, implement the corresponding method: initialize the default value

// Select multiple default values for initialization. If a default value is passed, the default value is displayed
multipleInit() {
    // If a default value is passed, render it into the component
    if (this.multipleValues.length > 0) {
        this.$refs.selectTree.setCheckedKeys(this.multipleValues);
        this.selectedNodes = this.$refs.selectTree.getCheckedNodes();
        this.value = this.selectedNodes.map(item= > item[this.defaultProps.label]); }},// Initialize the radio option default value
radioInit() {
    if (this.radioValue) {
        this.$refs.selectTree.setCheckedKeys([this.radioValue]);
        this.selectedNodes = this.$refs.selectTree.getCheckedNodes();
        this.value = this.selectedNodes[0] [this.defaultProps.label]; }}Copy the code

Method of toggling options

handleNodeClick(node, el) {
    this.selectedNodes = el.checkedNodes;
    if (this.multiple) {
        / / multi-select
        this.value = el.checkedNodes.map(item= > item[this.defaultProps.label]);
    } else {
        / / radio
        this.value = el.checkedNodes[0] [this.defaultProps.label]; }}Copy the code

Remove options

// Remove options (single remove)
removeTag(tag) {
    let arr = this.selectedNodes.filter(item= > item[this.defaultProps.label] === tag);
    this.$refs.selectTree.setChecked(arr[0].id, false);
    this.value.splice(this.value.indexOf(tag), 1);
},
// Clear the selected items (clear all)
clearHandle() {
    if (this.multiple) {
        this.value = [];
    } else {
        this.value = ' ';
    }
    this.$refs.selectTree.setCheckedKeys([]);
}
Copy the code
$emit ejects this event to the parent component to retrieve the selected id
getCheckedKeys() {
    return this.$refs.selectTree.getCheckedKeys()
},
// Call back when the node status changes
handleCheckChange(data, checked) {
    if (!this.multiple && checked === true) {
        / / radio
        this.$refs.selectTree.setCheckedNodes([data]); }}Copy the code

The source address: making