# el-select-tree

ElementUI's el-select combined with el-tree.

  • 2.1 Support custom menu header/footer.
  • 2.1 check-on-click-node is available with show-checkobx, default is false. Broken Change
  • 2.1 expand-on-click-node is available, default is true.
  • 2.1 Support virtual list.
  • 2.0 Comprehensively improve the utilization rate of original parts.

# Installation

npm install --save el-select-tree
import Vue from "vue";
import ElSelectTree from "el-select-tree";

Vue.use(ElSelectTree);

If your project does not depend on element-ui, you need to introduce additional component packages.

import "el-select-tree/lib/element-ui";
// If the project is loaded on demand, modify babel.config.js according to the official configuration.
// The complete style file is imported here.
// https://element.eleme.io/#/zh-CN/component/quickstart#an-xu-yin-ru
import "element-ui/lib/theme-chalk/index.css";

# Usage

# check-strictly

Any node can be selected, and the normal mode can only select leaf nodes.

use checkbox:
Click me to show code
<template>
  <div>
    <ElSelectTree v-model="value" :data="data" check-strictly></ElSelectTree>
    <el-divider direction="vertical"></el-divider>
    use checkbox:
    <ElSelectTree
      v-model="value"
      :data="data"
      check-strictly
      show-checkbox
    ></ElSelectTree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      value: '',
      data: [
        {
          label: '乌鲁木齐市',
          value: '2',
          children: [
            { label: '达坂城区', value: '7' },
            { label: '头屯河区', value: '8' },
            { label: '乌鲁木齐县', value: '9' },
          ],
        },
      ],
    };
  },
};
</script>

# filterable

Support for filtering tree nodes.

Click me to show code
<template>
  <ElSelectTree v-model="value" :data="data" filterable></ElSelectTree>
</template>

<script>
export default {
  data() {
    return {
      value: '',
      data: [
        {
          label: '乌鲁木齐市',
          value: '2',
          children: [
            { label: '达坂城区', value: '7' },
            { label: '头屯河区', value: '8' },
            { label: '乌鲁木齐县', value: '9' },
          ],
        },
      ],
    };
  },
};
</script>

# multiple

Multiple selection.

use checkbox and filterable:
Click me to show code
<template>
  <div>
    <ElSelectTree v-model="values" :data="data" multiple></ElSelectTree>
    <el-divider direction="vertical"></el-divider>
    use checkbox and filterable:
    <ElSelectTree
      v-model="values"
      :data="data"
      filterable
      multiple
      show-checkbox
    ></ElSelectTree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      values: [],
      data: [
        {
          label: '乌鲁木齐市',
          value: '2',
          children: [
            { label: '达坂城区', value: '7' },
            { label: '头屯河区', value: '8' },
            { label: '乌鲁木齐县', value: '9' },
          ],
        },
      ],
    };
  },
};
</script>

# props

Custom tree data props.

Click me to show code
<template>
  <ElSelectTree
    v-model="value"
    :data="data"
    :props="{
      value: 'id',
      label: (data) => data.name,
      children: 'child',
    }"
  ></ElSelectTree>
</template>

<script>
export default {
  data() {
    return {
      value: '',
      data: [
        {
          id: 1,
          name: 1,
          child: [{ id: 2, name: 2 }],
        },
      ],
    };
  },
};
</script>

# lazy-load

Lazy load tree nodes.

Click me to show code
<template>
  <ElSelectTree v-model="value" lazy :load="load"></ElSelectTree>
</template>

<script>
export default {
  data() {
    return {
      value: '',
    };
  },
  methods: {
    load(node, resolve) {
      if (node.data && node.data.isLeaf) return resolve([]);
      setTimeout(() => {
        resolve([
          {
            value: Date.now(),
            label: '懒加载节点',
            isLeaf: node.level === 3,
          },
        ]);
      }, 600);
    },
  },
};
</script>

# lazy-load-cache-data

Use cached data to display unloaded node names.

Click me to show code
<template>
  <ElSelectTree
    v-model="value"
    lazy
    :cache-data="[{ value: 2, label: '2-label' }]"
    :load="load"
  ></ElSelectTree>
</template>

<script>
export default {
  data() {
    return {
      lazyId: 0,
      value: 2,
    };
  },
  methods: {
    load(node, resolve) {
      setTimeout(() => {
        resolve([
          {
            value: ++this.lazyId,
            label: this.lazyId + '-label',
          },
        ]);
      }, 600);
    },
  },
};
</script>

# slot

Custom option content.

Click me to show code
<template>
  <ElSelectTree v-model="value" :data="data">
    <template slot-scope="{ data }">
      <i class="el-icon-document"></i>{{ data.label }}
    </template>
  </ElSelectTree>
</template>

<script>
export default {
  data() {
    return {
      value: '',
      data: [
        {
          label: '乌鲁木齐市',
          value: '2',
          children: [
            { label: '达坂城区', value: '7' },
            { label: '头屯河区', value: '8' },
            { label: '乌鲁木齐县', value: '9' },
          ],
        },
      ],
    };
  },
};
</script>

# slots-menu 2.1-beta

Custom menu header/footer.

Click me to show code
<template>
  <ElSelectTree v-model="value" :data="data" multiple show-checkbox>
    <template #header>
      <el-checkbox @change="handleSelectAll">全选</el-checkbox>
    </template>
    <template #footer>
      <el-button @click="handleAddOption" size="mini">添加选项</el-button>
    </template>
  </ElSelectTree>
</template>

<script>
export default {
  data() {
    return {
      value: [],
      data: [
        {
          label: '乌鲁木齐市',
          value: '2',
          children: [
            { label: '达坂城区', value: '7' },
            { label: '头屯河区', value: '8' },
            { label: '乌鲁木齐县', value: '9' },
          ],
        },
      ],
    };
  },
  methods: {
    handleSelectAll(val) {
      if (val) {
        this.value = this.data.flatMap((item) =>
          item.children.map((item) => item.value),
        );
      } else {
        this.value = [];
      }
    },
    handleAddOption() {
      this.data.push({
        value: Date.now(),
        label: 'New Option',
        children: [{ value: Date.now() + 1, label: 'New Option - Child 1' }],
      });
    },
  },
};
</script>

# render

Custom option content use render.

Click me to show code
<template>
  <ElSelectTree
    v-model="value"
    :data="data"
    :render-content="
      (h, { data, node }) => [h('i', { class: 'el-icon-document' }), data.label]
    "
  ></ElSelectTree>
</template>

<script>
export default {
  data() {
    return {
      value: '',
      data: [
        {
          label: '乌鲁木齐市',
          value: '2',
          children: [
            { label: '达坂城区', value: '7' },
            { label: '头屯河区', value: '8' },
            { label: '乌鲁木齐县', value: '9' },
          ],
        },
      ],
    };
  },
};
</script>

# with-form

Use with el-form.

Click me to show code
<template>
  <div>
    <el-form ref="elForm" :model="model">
      <el-form-item prop="value" label="select" required>
        <ElSelectTree
          v-model="model.value"
          :data="data"
          clearable
        ></ElSelectTree>
      </el-form-item>
    </el-form>
    <el-button @click="$refs.elForm.validate()">Validate</el-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      model: {
        value: '',
      },
      data: [
        {
          label: '乌鲁木齐市',
          value: '2',
          children: [
            { label: '达坂城区', value: '7' },
            { label: '头屯河区', value: '8' },
            { label: '乌鲁木齐县', value: '9' },
          ],
        },
      ],
    };
  },
};
</script>

# virtual Experimental 2.1-beta

Use virtual list. ElSelectTreeVirtual is optional, need register first.

npm i el-select-tree@2.1
import { ElSelectTreeVirtual } from "el-select-tree";

export default {
  components: {
    ElSelectTreeVirtual,
  },
};

WARNING

Use banReactive when the amount of data is large. Otherwise, performance will be slower.

const empty = reactive({});
const banReactive = (obj) => {
  // skip vue reactive
  obj.__ob__ = empty.__ob__;
  return obj;
};

export default {
  data() {
    return {
      data: banReactive(
        Array(100000)
          .fill("")
          .map((item, index) => ({ value: index, label: index + "" }))
      ),
    };
  },
};

# Props

el-select-tree inherits el-tree and el-select all props/methods/events/slots.

So no repeat here.

props methods events slots
el-select (opens new window) el-select (opens new window) el-select (opens new window) el-select (opens new window)
el-tree (opens new window) el-tree (opens new window) el-tree (opens new window) el-tree (opens new window)

# Own Props

Name Type Desc
cache-data Array The cache data for lazy load tree nodes, it can resolved correct label with unloaded nodes.

# Own Slots 2.1-beta

Name Desc
header menu header
footer menu footer
Last Updated: 4/25/2024, 1:41:28 PM