mirror of https://github.com/ElemeFE/element
chore: add new component tree-select (#21782)
parent
f14b5ba540
commit
56d60e4197
|
@ -87,5 +87,6 @@
|
|||
"empty": "./packages/empty/index.js",
|
||||
"descriptions": "./packages/descriptions/index.js",
|
||||
"descriptions-item": "./packages/descriptions-item/index.js",
|
||||
"result": "./packages/result/index.js"
|
||||
"result": "./packages/result/index.js",
|
||||
"tree-select": "./packages/tree-select/index.js"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,817 @@
|
|||
## TreeSelect
|
||||
|
||||
The tree selector of the dropdown menu, it combines the functions of components el-tree and el-select.
|
||||
|
||||
### Basic usage
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<template>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<p>click text to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<p>show-checkbox</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
show-checkbox
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Select any level
|
||||
|
||||
When using the check-strictly=true attribute, any node can be checked, otherwise only leaf nodes are supported.
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<p>click text to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
check-strictly
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<p>show-checkbox, only click checkbox to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
show-checkbox
|
||||
check-strictly
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Multiple Selection
|
||||
|
||||
Multiple selection using clicks or checkbox.
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="8">
|
||||
<p>click text to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
multiple
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<p>show checkbox</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
multiple
|
||||
show-checkbox
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<p>show checkbox with `check-strictly`</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value3"
|
||||
:data="data"
|
||||
multiple
|
||||
show-checkbox
|
||||
check-strictly
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: [],
|
||||
value2: [],
|
||||
value3: [],
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Clearable
|
||||
|
||||
You can clear tree-select using a clear icon.
|
||||
|
||||
Set clearable attribute for el-tree-select and a clear icon will appear.
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
clearable
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
multiple
|
||||
show-checkbox
|
||||
clearable
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Disabled Selection
|
||||
|
||||
Disable options using the disabled field.
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value"
|
||||
:data="data"
|
||||
/>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
disabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Filterable
|
||||
|
||||
Use keyword filtering or custom filtering methods. filterMethod can custom filter method for data.
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<p>filterable</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
filterable
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<p>filterMethod</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
filterable
|
||||
:filter-method="filterMethod"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
filterMethod(value, data) {
|
||||
return data.value.indexOf(value) !== -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### LazyLoad
|
||||
|
||||
Lazy loading of tree nodes, suitable for large data lists.
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-tree-select
|
||||
:props="props"
|
||||
placeholder="Select"
|
||||
v-model="value"
|
||||
clearable
|
||||
filterable
|
||||
lazy
|
||||
:filterMethod="filterMethod"
|
||||
:load="loadNode"
|
||||
node-key="id"
|
||||
/>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value: "",
|
||||
props: {
|
||||
label: "name",
|
||||
children: "zones",
|
||||
isLeaf: "leaf",
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadNode(node, resolve) {
|
||||
if (node.level === 0) {
|
||||
return resolve([{ id: "0", name: "Trunk" }]);
|
||||
}
|
||||
if (node.level > 3) return resolve([]);
|
||||
|
||||
setTimeout(() => {
|
||||
const data = [
|
||||
{
|
||||
id: `leaf-${node.level}`,
|
||||
name: `Leaf ${node.level}`,
|
||||
leaf: true,
|
||||
},
|
||||
{
|
||||
id: `branch-${node.level}`,
|
||||
name: `Branch ${node.level}`,
|
||||
},
|
||||
];
|
||||
resolve(data);
|
||||
}, 500);
|
||||
},
|
||||
|
||||
filterMethod(value, data) {
|
||||
if (!value) return true;
|
||||
return data.name.indexOf(value) !== -1;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
| Name | Description | Type | Accepted Values | Default|
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------- | --------------------------- | ----------------- | ------ |
|
||||
| value / v-model | binding value | boolean / string / number | — | — |
|
||||
| data | tree data | array | — | — |
|
||||
| multiple | whether multiple-select is activated | boolean | — | false |
|
||||
| disabled | whether Select is disabled | boolean | — | false |
|
||||
| size | size of Input | string | medium/small/mini | — |
|
||||
| clearable | whether select can be cleared | boolean | — | false |
|
||||
| collapse-tags | whether to collapse tags to a text when multiple selecting | boolean | — | false |
|
||||
| name | the name attribute of Tree-select input | string | — | — |
|
||||
| placeholder | placeholder | string | — | 请选择 |
|
||||
| filterable | whether Tree-select is filterable | boolean | — | false |
|
||||
| empty-text | displayed text when there is no data | String | — | — |
|
||||
| node-key | unique identity key name for nodes, its value should be unique across the whole tree | String | — | — |
|
||||
| props | configuration options, see the following table | object | — | — |
|
||||
| render-after-expand | whether to render child nodes only after a parent node is expanded for the first time | boolean | — | true |
|
||||
| load | method for loading subtree data, only works when lazy is true | function(node, resolve) | — | — |
|
||||
| default-expand-all | whether to expand all nodes by default | boolean | — | false |
|
||||
| auto-expand-parent | whether to expand father node when a child node is expanded | boolean | — | true |
|
||||
| show-checkbox | whether node is selectable | boolean | — | false |
|
||||
| check-strictly | whether checked state of a node not affects its father and child nodes when show-checkbox is true | boolean | — | false |
|
||||
| filter-method | custom filter method | Function(value, data, node) | — | — |
|
||||
| accordion | whether only one node among the same level can be expanded at one time | boolean | — | false |
|
||||
| indent | horizontal indentation of nodes in adjacent levels in pixels | number | — | 16 |
|
||||
| lazy | whether to lazy load leaf node, used with load attribute | boolean | — | false |
|
||||
| popper-append-to-body | whether to append the popper menu to body. If the positioning of the popper is wrong, you can try to set this prop to false | boolean | - | true |
|
||||
|
||||
### props
|
||||
|
||||
| Attribute| Description | Type | Accepted Values | Default |
|
||||
| -------- | ----------------------------------------------------------------------------- | ----------------------------- | -------------------| ----------------|
|
||||
| label | specify which key of node object is used as the node's label | string, function(data, node) | — | — |
|
||||
| children | specify which node object is used as the node's subtree | string | — | — |
|
||||
| disabled | specify which key of node object represents if node's checkbox is disabled | boolean, function(data, node) | — | — |
|
||||
| isLeaf | specify whether the node is a leaf node, only works when lazy load is enabled | boolean, function(data, node) | — | — |
|
||||
|
||||
### Events
|
||||
|
||||
| Method | Description | Parameters |
|
||||
| -------------- | --------------------------------------------------------------- | ------------------------------------------ |
|
||||
| change | triggers when the selected value changes | current selected value |
|
||||
| visible-change | triggers when the dropdown appears/disappears | true when it appears, and false otherwise |
|
||||
| remove-tag | triggers when a tag is removed in multiple mode | removed tag value |
|
||||
| clear | triggers when the clear icon is clicked in a clearable Select | — |
|
||||
| blur | triggers when Input blurs | (event: Event) |
|
||||
| focus | triggers when Input focuses | (event: Event) |
|
||||
|
|
@ -0,0 +1 @@
|
|||
## TreeSelect
|
|
@ -0,0 +1 @@
|
|||
## TreeSelect
|
|
@ -0,0 +1,821 @@
|
|||
## TreeSelect 树形选择器
|
||||
|
||||
含有下拉菜单的树形选择器,结合了 el-tree 和 el-select 两个组件的功能。
|
||||
|
||||
### 基础单选
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<template>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<p>click text to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<p>show-checkbox</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
show-checkbox
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 选择任意级别
|
||||
|
||||
当属性 check-strictly=true 时,任何节点都可以被选择,否则只有子节点可被选择。
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<p>click text to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
check-strictly
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<p>show-checkbox, only click checkbox to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
show-checkbox
|
||||
check-strictly
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 多选
|
||||
|
||||
通过点击或复选框选择多个选项。
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="8">
|
||||
<p>click text to select</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
multiple
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<p>show checkbox</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
multiple
|
||||
show-checkbox
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<p>show checkbox with `check-strictly`</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value3"
|
||||
:data="data"
|
||||
multiple
|
||||
show-checkbox
|
||||
check-strictly
|
||||
@change="handleNodeChange"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: [],
|
||||
value2: [],
|
||||
value3: [],
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 可清空选项
|
||||
|
||||
包含清空按钮,可将选择器清空为初始状态,为`el-tree-select`设置`clearable`属性,则可将选择器清空
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
clearable
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
multiple
|
||||
show-checkbox
|
||||
clearable
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleNodeChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 禁用选项
|
||||
|
||||
使用 disabled 字段禁用选项。
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value"
|
||||
:data="data"
|
||||
/>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
disabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 可筛选
|
||||
|
||||
使用关键字筛选或自定义筛选方法。 filterMethod可以自定义数据筛选的方法。
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<p>filterable</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value1"
|
||||
:data="data"
|
||||
filterable
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<p>filterMethod</p>
|
||||
<el-tree-select
|
||||
placeholder="Select"
|
||||
v-model="value2"
|
||||
:data="data"
|
||||
filterable
|
||||
:filter-method="filterMethod"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value1: "",
|
||||
value2: "",
|
||||
data: [
|
||||
{
|
||||
value: "1",
|
||||
label: "Level One 1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1",
|
||||
label: "Level Two 1-1",
|
||||
children: [
|
||||
{
|
||||
value: "1-1-1",
|
||||
label: "Level Three 1-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "Level One 2",
|
||||
children: [
|
||||
{
|
||||
value: "2-1",
|
||||
label: "Level Two 2-1",
|
||||
children: [
|
||||
{
|
||||
value: "2-1-1",
|
||||
label: "Level Three 2-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "2-2",
|
||||
label: "Level Two 2-2",
|
||||
children: [
|
||||
{
|
||||
value: "2-2-1",
|
||||
label: "Level Three 2-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "Level One 3",
|
||||
children: [
|
||||
{
|
||||
value: "3-1",
|
||||
label: "Level Two 3-1",
|
||||
children: [
|
||||
{
|
||||
value: "3-1-1",
|
||||
label: "Level Three 3-1-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "3-2",
|
||||
label: "Level Two 3-2",
|
||||
children: [
|
||||
{
|
||||
value: "3-2-1",
|
||||
label: "Level Three 3-2-1",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
filterMethod(value, data) {
|
||||
return data.value.indexOf(value) !== -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 懒加载
|
||||
|
||||
树节点懒加载,更加适合于数据量大的列表。
|
||||
|
||||
:::demo
|
||||
```html
|
||||
<el-tree-select
|
||||
:props="props"
|
||||
placeholder="Select"
|
||||
v-model="value"
|
||||
clearable
|
||||
filterable
|
||||
lazy
|
||||
:filterMethod="filterMethod"
|
||||
:load="loadNode"
|
||||
node-key="id"
|
||||
/>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
value: "",
|
||||
props: {
|
||||
label: "name",
|
||||
children: "zones",
|
||||
isLeaf: "leaf",
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadNode(node, resolve) {
|
||||
if (node.level === 0) {
|
||||
return resolve([{ id: "0", name: "Trunk" }]);
|
||||
}
|
||||
if (node.level > 3) return resolve([]);
|
||||
|
||||
setTimeout(() => {
|
||||
const data = [
|
||||
{
|
||||
id: `leaf-${node.level}`,
|
||||
name: `Leaf ${node.level}`,
|
||||
leaf: true,
|
||||
},
|
||||
{
|
||||
id: `branch-${node.level}`,
|
||||
name: `Branch ${node.level}`,
|
||||
},
|
||||
];
|
||||
resolve(data);
|
||||
}, 500);
|
||||
},
|
||||
|
||||
filterMethod(value, data) {
|
||||
if (!value) return true;
|
||||
return data.name.indexOf(value) !== -1;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
### Attributes
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
| --------------------- | ----------------------------------------------------------------------------------------------- | --------------------------- | ----------------- | ------ |
|
||||
| value / v-model | 绑定值 | boolean / string / number | — | — |
|
||||
| data | 展示数据 | array | — | — |
|
||||
| multiple | 是否多选 | boolean | — | false |
|
||||
| disabled | 是否禁用 | boolean | — | false |
|
||||
| size | 输入框尺寸 | string | medium/small/mini | — |
|
||||
| clearable | 是否可以清空选项 | boolean | — | false |
|
||||
| collapse-tags | 多选时是否将选中值按文字的形式展示 | boolean | — | false |
|
||||
| name | tree-select input 的 name 属性 | string | — | — |
|
||||
| placeholder | 占位符 | string | — | 请选择 |
|
||||
| filterable | 是否可搜索 | boolean | — | false |
|
||||
| empty-text | 内容为空的时候展示的文本 | String | — | — |
|
||||
| node-key | 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的 | String | — | — |
|
||||
| props | 配置选项,具体看下表 | object | — | — |
|
||||
| render-after-expand | 是否在第一次展开某个树节点后才渲染其子节点 | boolean | — | true |
|
||||
| load | 加载子树数据的方法,仅当 lazy 属性为 true 时生效 | function(node, resolve) | — | — |
|
||||
| default-expand-all | 是否默认展开所有节点 | boolean | — | false |
|
||||
| auto-expand-parent | 展开子节点的时候是否自动展开父节点 | boolean | — | true |
|
||||
| show-checkbox | 节点是否可被选择 | boolean | — | false |
|
||||
| check-strictly | 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false | boolean | — | false |
|
||||
| filter-method | 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏 | Function(value, data, node) | — | — |
|
||||
| accordion | 是否每次只打开一个同级树节点展开 | boolean | — | false |
|
||||
| indent | 相邻级节点间的水平缩进,单位为像素 | number | — | 16 |
|
||||
| lazy | 是否懒加载子节点,需与 load 方法结合使用 | boolean | — | false |
|
||||
| popper-append-to-body | 是否将弹出框插入至 body 元素。在弹出框的定位出现问题时,可将该属性设置为 false | boolean | - | true |
|
||||
|
||||
### props
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
| -------- | -------------------------------------------------------- | ----------------------------- | ------ | ------ |
|
||||
| label | 指定节点标签为节点对象的某个属性值 | string, function(data, node) | — | — |
|
||||
| children | 指定子树为节点对象的某个属性值 | string | — | — |
|
||||
| disabled | 指定节点选择框是否禁用为节点对象的某个属性值 | boolean, function(data, node) | — | — |
|
||||
| isLeaf | 指定节点是否为叶子节点,仅在指定了 lazy 属性的情况下生效 | boolean, function(data, node) | — | — |
|
||||
|
||||
### Events
|
||||
|
||||
| 事件名称 | 说明 | 回调参数 |
|
||||
| -------------- | ---------------------------------------- | ----------------------------- |
|
||||
| change | 选中值发生变化时触发 | 目前的选中值 |
|
||||
| visible-change | 下拉框出现/隐藏时触发 | 出现则为 true,隐藏则为 false |
|
||||
| remove-tag | 多选模式下移除 tag 时触发 | 移除的 tag 值 |
|
||||
| clear | 可清空的单选模式下用户点击清空按钮时触发 | — |
|
||||
| blur | 当 input 失去焦点时触发 | (event: Event) |
|
||||
| focus | 当 input 获得焦点时触发 | (event: Event) |
|
||||
|
||||
### Methods
|
||||
|
||||
| 方法名 | 说明 | 参数 |
|
||||
| ------ | ------------------------------- | ---- |
|
||||
| focus | 使 input 获取焦点 | - |
|
||||
| blur | 使 input 失去焦点,并隐藏下拉框 | - |
|
|
@ -104,6 +104,10 @@
|
|||
"path": "/cascader",
|
||||
"title": "Cascader 级联选择器"
|
||||
},
|
||||
{
|
||||
"path": "/tree-select",
|
||||
"title": "TreeSelect 树形选择器"
|
||||
},
|
||||
{
|
||||
"path": "/switch",
|
||||
"title": "Switch 开关"
|
||||
|
@ -422,6 +426,10 @@
|
|||
"path": "/cascader",
|
||||
"title": "Cascader"
|
||||
},
|
||||
{
|
||||
"path": "/tree-select",
|
||||
"title": "TreeSelect"
|
||||
},
|
||||
{
|
||||
"path": "/switch",
|
||||
"title": "Switch"
|
||||
|
|
|
@ -6,19 +6,20 @@
|
|||
|
||||
/* Transition
|
||||
-------------------------- */
|
||||
$--all-transition: all .3s cubic-bezier(.645,.045,.355,1) !default;
|
||||
$--all-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) !default;
|
||||
$--fade-transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
|
||||
$--fade-linear-transition: opacity 200ms linear !default;
|
||||
$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
|
||||
$--border-transition-base: border-color .2s cubic-bezier(.645,.045,.355,1) !default;
|
||||
$--color-transition-base: color .2s cubic-bezier(.645,.045,.355,1) !default;
|
||||
$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1),
|
||||
opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
|
||||
$--border-transition-base: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) !default;
|
||||
$--color-transition-base: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) !default;
|
||||
|
||||
/* Color
|
||||
-------------------------- */
|
||||
/// color|1|Brand Color|0
|
||||
$--color-primary: #409EFF !default;
|
||||
$--color-primary: #409eff !default;
|
||||
/// color|1|Background Color|4
|
||||
$--color-white: #FFFFFF !default;
|
||||
$--color-white: #ffffff !default;
|
||||
/// color|1|Background Color|4
|
||||
$--color-black: #000000 !default;
|
||||
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
|
||||
|
@ -31,11 +32,11 @@ $--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /
|
|||
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
|
||||
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
|
||||
/// color|1|Functional Color|1
|
||||
$--color-success: #67C23A !default;
|
||||
$--color-success: #67c23a !default;
|
||||
/// color|1|Functional Color|1
|
||||
$--color-warning: #E6A23C !default;
|
||||
$--color-warning: #e6a23c !default;
|
||||
/// color|1|Functional Color|1
|
||||
$--color-danger: #F56C6C !default;
|
||||
$--color-danger: #f56c6c !default;
|
||||
/// color|1|Functional Color|1
|
||||
$--color-info: #909399 !default;
|
||||
|
||||
|
@ -55,19 +56,19 @@ $--color-text-regular: #606266 !default;
|
|||
/// color|1|Font Color|2
|
||||
$--color-text-secondary: #909399 !default;
|
||||
/// color|1|Font Color|2
|
||||
$--color-text-placeholder: #C0C4CC !default;
|
||||
$--color-text-placeholder: #c0c4cc !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-base: #DCDFE6 !default;
|
||||
$--border-color-base: #dcdfe6 !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-light: #E4E7ED !default;
|
||||
$--border-color-light: #e4e7ed !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-lighter: #EBEEF5 !default;
|
||||
$--border-color-lighter: #ebeef5 !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-extra-light: #F2F6FC !default;
|
||||
$--border-color-extra-light: #f2f6fc !default;
|
||||
|
||||
// Background
|
||||
/// color|1|Background Color|4
|
||||
$--background-color-base: #F5F7FA !default;
|
||||
$--background-color-base: #f5f7fa !default;
|
||||
|
||||
/* Link
|
||||
-------------------------- */
|
||||
|
@ -91,9 +92,9 @@ $--border-radius-zero: 0 !default;
|
|||
|
||||
// Box-shadow
|
||||
/// boxShadow|1|Shadow|1
|
||||
$--box-shadow-base: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04) !default;
|
||||
$--box-shadow-base: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04) !default;
|
||||
// boxShadow|1|Shadow|1
|
||||
$--box-shadow-dark: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12) !default;
|
||||
$--box-shadow-dark: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.12) !default;
|
||||
/// boxShadow|1|Shadow|1
|
||||
$--box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
|
||||
|
@ -103,8 +104,8 @@ $--fill-base: $--color-white !default;
|
|||
|
||||
/* Typography
|
||||
-------------------------- */
|
||||
$--font-path: 'fonts' !default;
|
||||
$--font-display: 'auto' !default;
|
||||
$--font-path: "fonts" !default;
|
||||
$--font-display: "auto" !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
$--font-size-extra-large: 20px !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
|
@ -210,8 +211,6 @@ $--checkbox-button-checked-font-color: $--color-white !default;
|
|||
/// color||Color|0
|
||||
$--checkbox-button-checked-border-color: $--color-primary !default;
|
||||
|
||||
|
||||
|
||||
/* Radio
|
||||
-------------------------- */
|
||||
/// fontSize||Font|1
|
||||
|
@ -589,7 +588,6 @@ $--button-info-background-color: $--color-info !default;
|
|||
$--button-hover-tint-percent: 20% !default;
|
||||
$--button-active-shade-percent: 10% !default;
|
||||
|
||||
|
||||
/* cascader
|
||||
-------------------------- */
|
||||
$--cascader-height: 200px !default;
|
||||
|
@ -637,7 +635,7 @@ $--table-row-hover-background-color: $--background-color-base !default;
|
|||
$--table-current-row-background-color: $--color-primary-light-9 !default;
|
||||
/// color||Color|0
|
||||
$--table-header-background-color: $--color-white !default;
|
||||
$--table-fixed-box-shadow: 0 0 10px rgba(0, 0, 0, .12) !default;
|
||||
$--table-fixed-box-shadow: 0 0 10px rgba(0, 0, 0, 0.12) !default;
|
||||
|
||||
/* Pagination
|
||||
-------------------------- */
|
||||
|
@ -825,8 +823,8 @@ $--loading-fullscreen-spinner-size: 50px !default;
|
|||
|
||||
/* Scrollbar
|
||||
--------------------------*/
|
||||
$--scrollbar-background-color: rgba($--color-text-secondary, .3) !default;
|
||||
$--scrollbar-hover-background-color: rgba($--color-text-secondary, .5) !default;
|
||||
$--scrollbar-background-color: rgba($--color-text-secondary, 0.3) !default;
|
||||
$--scrollbar-hover-background-color: rgba($--color-text-secondary, 0.5) !default;
|
||||
|
||||
/* Carousel
|
||||
--------------------------*/
|
||||
|
@ -935,7 +933,7 @@ $--link-info-font-color: $--color-info !default;
|
|||
/// border||Other|4
|
||||
$--calendar-border: $--table-border !default;
|
||||
/// color||Other|4
|
||||
$--calendar-selected-background-color: #F2F8FE !default;
|
||||
$--calendar-selected-background-color: #f2f8fe !default;
|
||||
$--calendar-cell-width: 85px !default;
|
||||
|
||||
/* Form
|
||||
|
@ -948,7 +946,7 @@ $--form-label-font-size: $--font-size-base !default;
|
|||
/// color||Color|0
|
||||
$--avatar-font-color: #fff !default;
|
||||
/// color||Color|0
|
||||
$--avatar-background-color: #C0C4CC !default;
|
||||
$--avatar-background-color: #c0c4cc !default;
|
||||
/// fontSize||Font Size|1
|
||||
$--avatar-text-font-size: 14px !default;
|
||||
/// fontSize||Font Size|1
|
||||
|
@ -983,7 +981,7 @@ $--skeleton-to-color: #e6e6e6 !default;
|
|||
|
||||
/* Svg
|
||||
--------------- */
|
||||
$--svg-monochrome-grey: #DCDDE0 !default;
|
||||
$--svg-monochrome-grey: #dcdde0 !default;
|
||||
|
||||
/* Result
|
||||
-------------------------- */
|
||||
|
@ -998,6 +996,23 @@ $--result-success-color: $--color-success !default;
|
|||
$--result-warning-color: $--color-warning !default;
|
||||
$--result-danger-color: $--color-danger !default;
|
||||
|
||||
/* Tree-select
|
||||
-------------------------- */
|
||||
$--tree-select-font-size: $--font-size-base !default;
|
||||
$--tree-select-dropdown-border: solid 1px $--border-color-light !default;
|
||||
$--tree-select-multiple-input-color: $--color-text-placeholder !default;
|
||||
$--tree-select-dropdown-background: $--color-white !default;
|
||||
$--tree-select-option-selected-hover: $--background-color-base !default;
|
||||
$--tree-select-dropdown-max-height: 272px !default;
|
||||
$--tree-select-dropdown-padding: 6px 0 !default;
|
||||
$--tree-select-dropdown-empty-color: #999 !default;
|
||||
$--tree-select-dropdown-empty-padding: 10px 0 !default;
|
||||
|
||||
$--tree-select-mini-dropdown-max-height: 176px !default;
|
||||
$--tree-select-small-dropdown-max-height: 216px !default;
|
||||
$--tree-select-large-dropdown-max-height: 386px !default;
|
||||
|
||||
|
||||
/* Break-point
|
||||
--------------------------*/
|
||||
$--sm: 768px !default;
|
||||
|
@ -1006,23 +1021,49 @@ $--lg: 1200px !default;
|
|||
$--xl: 1920px !default;
|
||||
|
||||
$--breakpoints: (
|
||||
'xs' : (max-width: $--sm - 1),
|
||||
'sm' : (min-width: $--sm),
|
||||
'md' : (min-width: $--md),
|
||||
'lg' : (min-width: $--lg),
|
||||
'xl' : (min-width: $--xl)
|
||||
"xs": (
|
||||
max-width: $--sm - 1,
|
||||
),
|
||||
"sm": (
|
||||
min-width: $--sm,
|
||||
),
|
||||
"md": (
|
||||
min-width: $--md,
|
||||
),
|
||||
"lg": (
|
||||
min-width: $--lg,
|
||||
),
|
||||
"xl": (
|
||||
min-width: $--xl,
|
||||
),
|
||||
);
|
||||
|
||||
$--breakpoints-spec: (
|
||||
'xs-only' : (max-width: $--sm - 1),
|
||||
'sm-and-up' : (min-width: $--sm),
|
||||
'sm-only': "(min-width: #{$--sm}) and (max-width: #{$--md - 1})",
|
||||
'sm-and-down': (max-width: $--md - 1),
|
||||
'md-and-up' : (min-width: $--md),
|
||||
'md-only': "(min-width: #{$--md}) and (max-width: #{$--lg - 1})",
|
||||
'md-and-down': (max-width: $--lg - 1),
|
||||
'lg-and-up' : (min-width: $--lg),
|
||||
'lg-only': "(min-width: #{$--lg}) and (max-width: #{$--xl - 1})",
|
||||
'lg-and-down': (max-width: $--xl - 1),
|
||||
'xl-only' : (min-width: $--xl),
|
||||
"xs-only": (
|
||||
max-width: $--sm - 1,
|
||||
),
|
||||
"sm-and-up": (
|
||||
min-width: $--sm,
|
||||
),
|
||||
"sm-only": "(min-width: #{$--sm}) and (max-width: #{$--md - 1})",
|
||||
"sm-and-down": (
|
||||
max-width: $--md - 1,
|
||||
),
|
||||
"md-and-up": (
|
||||
min-width: $--md,
|
||||
),
|
||||
"md-only": "(min-width: #{$--md}) and (max-width: #{$--lg - 1})",
|
||||
"md-and-down": (
|
||||
max-width: $--lg - 1,
|
||||
),
|
||||
"lg-and-up": (
|
||||
min-width: $--lg,
|
||||
),
|
||||
"lg-only": "(min-width: #{$--lg}) and (max-width: #{$--xl - 1})",
|
||||
"lg-and-down": (
|
||||
max-width: $--xl - 1,
|
||||
),
|
||||
"xl-only": (
|
||||
min-width: $--xl,
|
||||
),
|
||||
);
|
||||
|
|
|
@ -85,3 +85,4 @@
|
|||
@import "./descriptions.scss";
|
||||
@import "./descriptions-item.scss";
|
||||
@import "./result.scss";
|
||||
@import "./tree-select.scss";
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
@import "mixins/mixins";
|
||||
@import "common/var";
|
||||
|
||||
@include b(tree-select) {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 240px;
|
||||
|
||||
.el-tree-select__tags > span {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.el-input__inner {
|
||||
cursor: pointer;
|
||||
padding-right: 35px;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
display: block;
|
||||
& .el-tree-select__caret {
|
||||
transition: transform 0.3s;
|
||||
transform: rotateZ(180deg);
|
||||
cursor: pointer;
|
||||
|
||||
@include when(reverse) {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
& .el-icon-reload {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
& .el-input__inner {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include e(input) {
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
margin-left: 15px;
|
||||
color: $--tree-select-multiple-input-color;
|
||||
font-size: $--tree-select-font-size;
|
||||
appearance: none;
|
||||
height: 28px;
|
||||
background-color: transparent;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@include e(tags) {
|
||||
position: absolute;
|
||||
line-height: normal;
|
||||
white-space: normal;
|
||||
z-index: $--index-normal;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.el-tag {
|
||||
box-sizing: border-box;
|
||||
border-color: transparent;
|
||||
margin: 2px 0 2px 6px;
|
||||
background-color: #f0f2f5;
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
align-items: center;
|
||||
|
||||
&__close.el-icon-close {
|
||||
background-color: $--color-text-placeholder;
|
||||
top: 0;
|
||||
color: $--color-white;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: $--color-text-secondary;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: block;
|
||||
transform: translate(0, .5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include b(tree-select-dropdown) {
|
||||
position: absolute;
|
||||
z-index: #{$--index-top + 1};
|
||||
border-radius: $--border-radius-base;
|
||||
border: $--tree-select-dropdown-border;
|
||||
box-sizing: border-box;
|
||||
background-color: $--tree-select-dropdown-background;
|
||||
margin: 0 0 5px;
|
||||
|
||||
@include b(tree-select-dropdown__wrap) {
|
||||
max-height: $--tree-select-dropdown-max-height;
|
||||
}
|
||||
|
||||
@include b(tree-select-dropdown__list) {
|
||||
list-style: none;
|
||||
padding: $--tree-select-dropdown-padding;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
.el-tree-node {
|
||||
&:focus {
|
||||
> .el-tree-node__content:not(.is-disabled) {
|
||||
background: $--tree-select-option-selected-hover;
|
||||
}
|
||||
}
|
||||
.el-tree-node__content {
|
||||
transition: background-color 0.3s;
|
||||
color: $--color-text-primary;
|
||||
.el-tree-node__content-text {
|
||||
font-size: $--tree-select-font-size;
|
||||
}
|
||||
&:hover:not(.is-disabled),
|
||||
&:focus:not(.is-disabled) {
|
||||
background: $--tree-select-option-selected-hover;
|
||||
color: $--color-text-primary;
|
||||
}
|
||||
> .is-disabled {
|
||||
cursor: not-allowed;
|
||||
color: $--color-text-secondary;
|
||||
}
|
||||
> .is-selected {
|
||||
color: $--color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include b(tree-select-dropdown__empty) {
|
||||
padding: $--tree-select-dropdown-empty-padding;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
color: $--tree-select-dropdown-empty-color;
|
||||
font-size: $--tree-select-font-size;
|
||||
}
|
||||
|
||||
@include m(mini) {
|
||||
@include b(tree-select-dropdown__wrap) {
|
||||
max-height: $--tree-select-mini-dropdown-max-height;
|
||||
}
|
||||
}
|
||||
|
||||
@include m(small) {
|
||||
@include b(tree-select-dropdown__wrap) {
|
||||
max-height: $--tree-select-small-dropdown-max-height;
|
||||
}
|
||||
}
|
||||
|
||||
@include m(large) {
|
||||
@include b(tree-select-dropdown__wrap) {
|
||||
max-height: $--tree-select-large-dropdown-max-height;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import TreeSelect from './src/main';
|
||||
|
||||
/* istanbul ignore next */
|
||||
TreeSelect.install = function(Vue) {
|
||||
Vue.component(TreeSelect.name, TreeSelect);
|
||||
};
|
||||
|
||||
export default TreeSelect;
|
|
@ -0,0 +1,771 @@
|
|||
<template>
|
||||
<div
|
||||
class="el-tree-select"
|
||||
v-clickoutside="handleClose"
|
||||
@click.stop="toggleMenu"
|
||||
>
|
||||
<div
|
||||
class="el-tree-select__tags"
|
||||
v-if="multiple"
|
||||
ref="tags"
|
||||
:style="{ 'max-width': inputWidth - 32 + 'px', width: '100%' }"
|
||||
>
|
||||
<span v-if="collapseTags && selected.length">
|
||||
<el-tag
|
||||
:closable="!selectDisabled"
|
||||
:size="collapseTagSize"
|
||||
:hit="selected[0].hitState"
|
||||
type="info"
|
||||
@close="deleteTag($event, selected[0])"
|
||||
disable-transitions
|
||||
>{{ selected[0].label }}</el-tag
|
||||
>
|
||||
<el-tag
|
||||
v-if="selected.length > 1"
|
||||
:closable="false"
|
||||
:size="collapseTagSize"
|
||||
type="info"
|
||||
disable-transitions
|
||||
>
|
||||
+ {{ selected.length - 1 }}
|
||||
</el-tag>
|
||||
</span>
|
||||
|
||||
<transition-group
|
||||
v-if="!collapseTags"
|
||||
name="el-popper-in-center"
|
||||
@after-leave="resetInputHeight"
|
||||
>
|
||||
<el-tag
|
||||
v-for="item in selected"
|
||||
:key="item.data.value"
|
||||
:closable="!selectDisabled"
|
||||
:size="collapseTagSize"
|
||||
:hit="item.hitState"
|
||||
type="info"
|
||||
@close="deleteTag($event, item)"
|
||||
disable-transitions
|
||||
>
|
||||
{{ item.data.label }}
|
||||
</el-tag>
|
||||
</transition-group>
|
||||
|
||||
<input
|
||||
v-if="filterable"
|
||||
v-model="query"
|
||||
ref="input"
|
||||
type="text"
|
||||
class="el-tree-select__input"
|
||||
:disabled="disabled"
|
||||
@focus="handleFocus"
|
||||
@blur="softFocus = false"
|
||||
@keyup="managePlaceholder"
|
||||
@keydown="resetInputState"
|
||||
@keydown.down.prevent="handleNavigate('next')"
|
||||
@keydown.up.prevent="handleNavigate('prev')"
|
||||
@keydown.esc.stop.prevent="visible = false"
|
||||
@keydown.delete="deletePrevTag"
|
||||
@keydown.tab="visible = false"
|
||||
@compositionstart="handleComposition"
|
||||
@compositionupdate="handleComposition"
|
||||
@compositionend="handleComposition"
|
||||
@input="debouncedQueryChange"
|
||||
:style="{
|
||||
'flex-grow': '1',
|
||||
width: inputLength / (inputWidth - 32) + '%',
|
||||
'max-width': inputWidth - 42 + 'px',
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<el-input
|
||||
:class="{ 'is-focus': visible }"
|
||||
ref="reference"
|
||||
type="text"
|
||||
v-model="selectedLabel"
|
||||
:name="name"
|
||||
:id="id"
|
||||
:placeholder="currentPlaceholder"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:size="treeSelectSize"
|
||||
:validate-event="false"
|
||||
:tabindex="multiple && filterable ? '-1' : null"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@input="debouncedOnInputChange"
|
||||
@keydown.native.down.stop.prevent="handleNavigate('next')"
|
||||
@keydown.native.up.stop.prevent="handleNavigate('prev')"
|
||||
@keydown.native.esc.stop.prevent="visible = false"
|
||||
@keydown.native.tab="visible = false"
|
||||
@compositionstart="handleComposition"
|
||||
@compositionupdate="handleComposition"
|
||||
@compositionend="handleComposition"
|
||||
@mouseenter.native="inputHovering = true"
|
||||
@mouseleave.native="inputHovering = false"
|
||||
>
|
||||
<template slot="prefix" v-if="$slots.prefix">
|
||||
<slot name="prefix"></slot>
|
||||
</template>
|
||||
<template slot="suffix">
|
||||
<i v-if="loading" class="el-tree-select__caret el-icon-reload"></i>
|
||||
<template v-if="!loading">
|
||||
<i v-show="!showClose" :class="['el-tree-select__caret', 'el-input__icon', 'el-icon-' + iconDirection]"></i>
|
||||
<i v-if="showClose" class="el-tree-select__caret el-input__icon el-icon-circle-close" @click="handleClearClick"></i>
|
||||
</template>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<transition name="el-zoom-in-top" @afterLeave="doDestroy">
|
||||
<el-tree-select-dropdown
|
||||
ref="popper"
|
||||
:append-to-body="popperAppendToBody"
|
||||
v-show="visible"
|
||||
:class="[
|
||||
treeSelectSize ? `el-tree-select-dropdown--${treeSelectSize}` : '',
|
||||
]"
|
||||
>
|
||||
<el-scrollbar
|
||||
tag="ul"
|
||||
v-show="lazy || !loading"
|
||||
wrap-class="el-tree-select-dropdown__wrap"
|
||||
view-class="el-tree-select-dropdown__list"
|
||||
ref="scrollbar"
|
||||
:class="{
|
||||
'is-empty': query && filteredOptionsCount === 0,
|
||||
}"
|
||||
>
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="data"
|
||||
:node-key="nodeKey"
|
||||
:expand-on-click-node="!lazy && (!checkStrictly || !showCheckbox)"
|
||||
:check-strictly="checkStrictly"
|
||||
:show-checkbox="showCheckbox"
|
||||
:accordion="accordion"
|
||||
:default-expanded-keys="defaultExpandedKeys"
|
||||
:filter-node-method="filterMethod ? filterMethod : filterNodeMethod"
|
||||
:props="props"
|
||||
:lazy="lazy"
|
||||
:load="load"
|
||||
:emptyText="emptyText"
|
||||
:renderAfterExpand="renderAfterExpand"
|
||||
:defaultExpandAll="defaultExpandAll"
|
||||
:autoExpandParent="autoExpandParent"
|
||||
:indent="indent"
|
||||
:iconClass="iconClass"
|
||||
@node-click="handleNodeClick"
|
||||
@check="handleNodeCheck"
|
||||
>
|
||||
<span
|
||||
slot-scope="{ node, data }"
|
||||
:class="{
|
||||
'el-tree-node__content-text': true,
|
||||
'is-selected': node.selected,
|
||||
'is-disabled': node.disabled
|
||||
}"
|
||||
>
|
||||
{{ data[props['label']] }}
|
||||
</span>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</el-tree-select-dropdown>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/babel">
|
||||
import ElTag from 'element-ui/packages/tag';
|
||||
import ElInput from 'element-ui/packages/input';
|
||||
import ElTree from 'element-ui/packages/tree';
|
||||
import ElScrollbar from 'element-ui/packages/scrollbar';
|
||||
import ElTreeSelectDropdown from './tree-select-dropdown';
|
||||
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||
import {
|
||||
addResizeListener,
|
||||
removeResizeListener
|
||||
} from 'element-ui/src/utils/resize-event';
|
||||
import Emitter from 'element-ui/src/mixins/emitter';
|
||||
import Locale from 'element-ui/src/mixins/locale';
|
||||
import debounce from 'throttle-debounce/debounce';
|
||||
import { valueEquals } from 'element-ui/src/utils/util';
|
||||
import { isKorean } from 'element-ui/src/utils/shared';
|
||||
export default {
|
||||
name: 'ElTreeSelect',
|
||||
|
||||
directives: { Clickoutside },
|
||||
|
||||
mixins: [Emitter, Locale],
|
||||
|
||||
inject: {
|
||||
elForm: {
|
||||
default: ''
|
||||
},
|
||||
|
||||
elFormItem: {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
|
||||
components: { ElTag, ElInput, ElTree, ElScrollbar, ElTreeSelectDropdown },
|
||||
|
||||
props: {
|
||||
name: String,
|
||||
id: String,
|
||||
nodeKey: {
|
||||
type: [String, Number],
|
||||
default: 'value'
|
||||
},
|
||||
value: {
|
||||
required: true,
|
||||
type: [String, Number, Array]
|
||||
},
|
||||
disabled: Boolean,
|
||||
clearable: Boolean,
|
||||
filterable: Boolean,
|
||||
multiple: Boolean,
|
||||
loading: Boolean,
|
||||
collapseTags: Boolean,
|
||||
showCheckbox: Boolean,
|
||||
accordion: Boolean,
|
||||
filterMethod: Function,
|
||||
popperAppendToBody: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
checkStrictly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
load: Function,
|
||||
data: Array,
|
||||
props: {
|
||||
default() {
|
||||
return {
|
||||
value: 'value',
|
||||
label: 'label',
|
||||
children: 'children',
|
||||
disabled: 'disabled'
|
||||
};
|
||||
}
|
||||
},
|
||||
lazy: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
emptyText: {
|
||||
type: String
|
||||
},
|
||||
renderAfterExpand: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
defaultExpandAll: Boolean,
|
||||
autoExpandParent: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
indent: {
|
||||
type: Number,
|
||||
default: 22
|
||||
},
|
||||
iconClass: String
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
selectedLabel: '',
|
||||
visible: false,
|
||||
softFocus: false,
|
||||
currentPlaceholder: '',
|
||||
inputHovering: false,
|
||||
selected: this.multiple ? [] : {},
|
||||
query: '',
|
||||
filteredOptionsCount: 0,
|
||||
cachedPlaceHolder: '',
|
||||
menuVisibleOnFocus: false,
|
||||
defaultExpandedKeys: [],
|
||||
isOnComposition: false,
|
||||
isSilentBlur: false,
|
||||
inputWidth: 0,
|
||||
inputLength: 20
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
selectDisabled() {
|
||||
return this.disabled;
|
||||
},
|
||||
|
||||
iconDirection() {
|
||||
return this.visible ? 'arrow-up is-reverse' : 'arrow-up';
|
||||
},
|
||||
|
||||
readonly() {
|
||||
return !this.filterable || this.multiple || !this.visible;
|
||||
},
|
||||
|
||||
treeSelectSize() {
|
||||
return this.size || this._elFormItemSize || (this.elForm || {}).size;
|
||||
},
|
||||
|
||||
_elFormItemSize() {
|
||||
return (this.elFormItem || {}).elFormItemSize;
|
||||
},
|
||||
|
||||
showClose() {
|
||||
const hasValue =
|
||||
this.value !== undefined && this.value !== null && this.value !== '';
|
||||
return this.clearable && this.inputHovering && hasValue && !this.disabled;
|
||||
},
|
||||
|
||||
propPlaceholder() {
|
||||
return typeof this.placeholder !== 'undefined'
|
||||
? this.placeholder
|
||||
: this.t('el.select.placeholder');
|
||||
},
|
||||
|
||||
collapseTagSize() {
|
||||
return ['small', 'mini'].indexOf(this.size) > -1
|
||||
? 'mini'
|
||||
: 'small';
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
propPlaceholder(val) {
|
||||
this.cachedPlaceHolder = this.currentPlaceholder = val;
|
||||
},
|
||||
|
||||
value(val, oldVal) {
|
||||
if (this.multiple) {
|
||||
this.$nextTick(() => {
|
||||
this.resetInputHeight();
|
||||
this.broadcast('TuTreeSelectDropdown', 'updatePopper');
|
||||
});
|
||||
if (
|
||||
(val && val.length > 0) ||
|
||||
(this.$refs.input && this.query !== '')
|
||||
) {
|
||||
this.currentPlaceholder = '';
|
||||
} else {
|
||||
this.currentPlaceholder = this.cachedPlaceHolder;
|
||||
}
|
||||
}
|
||||
this.query = '';
|
||||
this.handleQueryChange(this.query);
|
||||
this.setOldSelected(oldVal);
|
||||
this.setSelected();
|
||||
if (!valueEquals(val, oldVal)) {
|
||||
this.dispatch('ElFormItem', 'el.form.change', val);
|
||||
}
|
||||
},
|
||||
|
||||
visible(val, oldVal) {
|
||||
if (!val) {
|
||||
this.broadcast('ElTreeSelectDropdown', 'destroyPopper');
|
||||
if (this.$refs.input) {
|
||||
this.$refs.input.blur();
|
||||
}
|
||||
this.query = '';
|
||||
this.inputLength = 20;
|
||||
this.menuVisibleOnFocus = false;
|
||||
} else {
|
||||
if (this.multiple) {
|
||||
this.resetInputHeight();
|
||||
} else {
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.broadcast('ElTreeSelectDropdown', 'updatePopper');
|
||||
});
|
||||
}
|
||||
this.$emit('visible-change', val);
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.cachedPlaceHolder = this.currentPlaceholder = this.propPlaceholder;
|
||||
|
||||
if (this.multiple && !Array.isArray(this.value)) {
|
||||
this.$emit('input', []);
|
||||
}
|
||||
if (!this.multiple && Array.isArray(this.value)) {
|
||||
this.$emit('input', '');
|
||||
}
|
||||
|
||||
this.debouncedOnInputChange = debounce(this.debounce, () => {
|
||||
this.onInputChange();
|
||||
});
|
||||
|
||||
this.debouncedQueryChange = debounce(this.debounce, (e) => {
|
||||
this.handleQueryChange(e.target.value);
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.multiple && Array.isArray(this.value) && this.value.length > 0) {
|
||||
this.currentPlaceholder = '';
|
||||
}
|
||||
addResizeListener(this.$el, this.handleResize);
|
||||
const reference = this.$refs.reference;
|
||||
if (reference && reference.$el) {
|
||||
const sizeMap = {
|
||||
medium: 36,
|
||||
small: 32,
|
||||
mini: 28
|
||||
};
|
||||
const input = reference.$el.querySelector('input');
|
||||
this.initialInputHeight =
|
||||
input.getBoundingClientRect().height || sizeMap[this.treeSelectSize];
|
||||
}
|
||||
addResizeListener(this.$el, this.handleResize);
|
||||
this.$nextTick(() => {
|
||||
if (reference && reference.$el) {
|
||||
this.inputWidth = reference.$el.getBoundingClientRect().width;
|
||||
}
|
||||
});
|
||||
this.setSelected();
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
if (this.$el && this.handleResize) {
|
||||
removeResizeListener(this.$el, this.handleResize);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.visible = false;
|
||||
},
|
||||
|
||||
toggleMenu() {
|
||||
if (!this.selectDisabled) {
|
||||
if (this.menuVisibleOnFocus) {
|
||||
this.menuVisibleOnFocus = false;
|
||||
} else {
|
||||
this.visible = !this.visible;
|
||||
}
|
||||
if (this.visible) {
|
||||
(this.$refs.input || this.$refs.reference).focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setSoftFocus() {
|
||||
this.softFocus = true;
|
||||
const input = this.$refs.input || this.$refs.reference;
|
||||
if (input) {
|
||||
input.focus();
|
||||
}
|
||||
},
|
||||
|
||||
handleFocus(event) {
|
||||
if (!this.softFocus) {
|
||||
if (this.filterable) {
|
||||
if (this.filterable && !this.visible) {
|
||||
this.menuVisibleOnFocus = true;
|
||||
}
|
||||
this.visible = true;
|
||||
}
|
||||
this.$emit('focus', event);
|
||||
} else {
|
||||
this.softFocus = false;
|
||||
}
|
||||
},
|
||||
|
||||
blur() {
|
||||
this.visible = false;
|
||||
this.$refs.reference.blur();
|
||||
},
|
||||
|
||||
handleBlur(event) {
|
||||
setTimeout(() => {
|
||||
if (this.isSilentBlur) {
|
||||
this.isSilentBlur = false;
|
||||
} else {
|
||||
this.$emit('blur', event);
|
||||
}
|
||||
}, 50);
|
||||
this.softFocus = false;
|
||||
},
|
||||
|
||||
handleNavigate(direction) {
|
||||
if (this.isOnComposition) return;
|
||||
const tree = this.$refs.tree;
|
||||
tree.initFocusedItem(direction);
|
||||
},
|
||||
|
||||
handleComposition(event) {
|
||||
const text = event.target.value;
|
||||
if (event.type === 'compositionend') {
|
||||
this.isOnComposition = false;
|
||||
this.$nextTick((_) => this.handleQueryChange(text));
|
||||
} else {
|
||||
const lastCharacter = text[text.length - 1] || '';
|
||||
this.isOnComposition = !isKorean(lastCharacter);
|
||||
}
|
||||
},
|
||||
|
||||
onInputChange() {
|
||||
if (this.filterable && this.query !== this.selectedLabel) {
|
||||
this.query = this.selectedLabel;
|
||||
this.handleQueryChange(this.query);
|
||||
}
|
||||
},
|
||||
|
||||
handleClearClick(event) {
|
||||
event.stopPropagation();
|
||||
const value = this.multiple ? [] : '';
|
||||
this.$emit('input', value);
|
||||
this.emitChange(value);
|
||||
this.visible = false;
|
||||
this.$emit('clear');
|
||||
},
|
||||
|
||||
deleteTag(event, node) {
|
||||
event.stopPropagation();
|
||||
this.handleMultipSelect(node.data, node);
|
||||
this.$emit('remove-tag', node);
|
||||
},
|
||||
|
||||
managePlaceholder() {
|
||||
if (this.currentPlaceholder !== '') {
|
||||
this.currentPlaceholder = this.$refs.input.value
|
||||
? ''
|
||||
: this.cachedPlaceHolder;
|
||||
}
|
||||
},
|
||||
|
||||
resetInputState(e) {
|
||||
if (e.keyCode !== 8) this.toggleLastOptionHitState(false);
|
||||
this.inputLength = this.$refs.input.value.length * 15 + 20;
|
||||
this.resetInputHeight();
|
||||
},
|
||||
|
||||
toggleLastOptionHitState(hit) {
|
||||
if (!Array.isArray(this.selected)) return;
|
||||
const option = this.selected[this.selected.length - 1];
|
||||
if (!option) return;
|
||||
|
||||
if (hit === true || hit === false) {
|
||||
option.hitState = hit;
|
||||
return hit;
|
||||
}
|
||||
option.hitState = !option.hitState;
|
||||
return option.hitState;
|
||||
},
|
||||
|
||||
deletePrevTag(e) {
|
||||
if (e.target.value.length <= 0 && !this.toggleLastOptionHitState()) {
|
||||
const value = this.value.slice();
|
||||
value.pop();
|
||||
this.$emit('input', value);
|
||||
this.emitChange(value);
|
||||
}
|
||||
},
|
||||
|
||||
handleQueryChange(val) {
|
||||
if (this.isOnComposition) return;
|
||||
const tree = this.$refs.tree;
|
||||
tree.filter(val);
|
||||
},
|
||||
|
||||
filterNodeMethod(value, data) {
|
||||
if (!value) return true;
|
||||
return data.label.indexOf(value) !== -1;
|
||||
},
|
||||
|
||||
handleResize() {
|
||||
this.resetInputWidth();
|
||||
if (this.multiple) this.resetInputHeight();
|
||||
},
|
||||
|
||||
doDestroy() {
|
||||
this.$refs.popper && this.$refs.popper.doDestroy();
|
||||
},
|
||||
|
||||
resetInputWidth() {
|
||||
this.inputWidth =
|
||||
this.$refs.reference &&
|
||||
this.$refs.reference.$el.getBoundingClientRect().width;
|
||||
},
|
||||
|
||||
resetInputHeight() {
|
||||
if (this.collapseTags && !this.filterable) return;
|
||||
this.$nextTick(() => {
|
||||
if (!this.$refs.reference) return;
|
||||
let inputChildNodes = this.$refs.reference.$el.childNodes;
|
||||
let input = [].filter.call(
|
||||
inputChildNodes,
|
||||
(item) => item.tagName === 'INPUT'
|
||||
)[0];
|
||||
const tags = this.$refs.tags;
|
||||
const tagsHeight = tags
|
||||
? Math.round(tags.getBoundingClientRect().height)
|
||||
: 0;
|
||||
const sizeInMap = this.initialInputHeight || 40;
|
||||
input.style.height =
|
||||
this.selected.length === 0
|
||||
? sizeInMap + 'px'
|
||||
: Math.max(
|
||||
tags ? tagsHeight + (tagsHeight > sizeInMap ? 6 : 0) : 0,
|
||||
sizeInMap
|
||||
) + 'px';
|
||||
if (this.visible && this.emptyText !== false) {
|
||||
this.broadcast('ElTreeSelectDropdown', 'updatePopper');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
emitChange(val) {
|
||||
if (!valueEquals(this.value, val)) {
|
||||
this.$emit('change', val);
|
||||
}
|
||||
},
|
||||
|
||||
setSelected() {
|
||||
const tree = this.$refs.tree;
|
||||
if (this.multiple) {
|
||||
const selected = [];
|
||||
if (Array.isArray(this.value)) {
|
||||
if (this.showCheckbox) {
|
||||
tree.setCheckedKeys(this.value);
|
||||
}
|
||||
this.value.forEach((val) => {
|
||||
const node = tree.getNode(val);
|
||||
if (node) {
|
||||
this.$set(node, 'selected', true);
|
||||
this.$set(node, 'hitState', false);
|
||||
selected.push(node);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.selected = selected;
|
||||
} else {
|
||||
const node = tree.getNode(this.value);
|
||||
if (node) {
|
||||
if (this.showCheckbox) {
|
||||
tree.setCheckedKeys([this.value]);
|
||||
}
|
||||
this.$set(node, 'selected', true);
|
||||
this.selected = node;
|
||||
this.selectedLabel = node.label;
|
||||
} else {
|
||||
this.selected = {};
|
||||
this.selectedLabel = '';
|
||||
if (this.showCheckbox) {
|
||||
tree.setCheckedKeys([]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setOldSelected(oldVal) {
|
||||
const tree = this.$refs.tree;
|
||||
if (this.multiple) {
|
||||
if (Array.isArray(oldVal)) {
|
||||
oldVal.forEach((val) => {
|
||||
const node = tree.getNode(val);
|
||||
if (node) {
|
||||
this.$set(node, 'selected', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const oldNode = tree.getNode(oldVal);
|
||||
if (oldNode) {
|
||||
this.$set(oldNode, 'selected', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
findNode(tree, func) {
|
||||
for (const node of tree.childNodes) {
|
||||
if (node.data && node.disabled) break;
|
||||
if (func(node)) return node;
|
||||
if (node.childNodes && node.childNodes.length) {
|
||||
const res = this.findNode(node, func);
|
||||
if (res) return res;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
handleNodeCheck(data, state, node) {
|
||||
const { label } = this.props;
|
||||
if (this.multiple) {
|
||||
this.$emit('input', state.checkedKeys);
|
||||
this.emitChange(state.checkedKeys);
|
||||
} else {
|
||||
let currentValue = '';
|
||||
let currentLabel = '';
|
||||
let currentNode = '';
|
||||
currentNode = this.checkStrictly
|
||||
? node
|
||||
: this.findNode(node, (node) => node.isLeaf) || node;
|
||||
const isCheckedNode = this.checkStrictly
|
||||
? currentNode.checked
|
||||
: currentNode.checked &&
|
||||
!this.findNode(
|
||||
node,
|
||||
(node) => node.data[this.nodeKey] === this.value
|
||||
);
|
||||
if (isCheckedNode) {
|
||||
currentLabel = currentNode.data[label];
|
||||
currentValue = currentNode.data[this.nodeKey];
|
||||
this.$set(currentNode, 'selected', true);
|
||||
}
|
||||
this.selectedLabel = currentLabel;
|
||||
this.$emit('input', currentValue);
|
||||
this.emitChange(currentValue);
|
||||
}
|
||||
this.setSoftFocus();
|
||||
},
|
||||
|
||||
handleNodeClick(data, node) {
|
||||
if (this.showCheckbox || node.disabled) return;
|
||||
if (!this.checkStrictly && node.childNodes.length !== 0) return;
|
||||
if (this.multiple) {
|
||||
this.handleMultipSelect(data, node);
|
||||
} else {
|
||||
this.handleSingleSelect(data, node);
|
||||
}
|
||||
this.setSoftFocus();
|
||||
},
|
||||
|
||||
handleMultipSelect(data, node) {
|
||||
const currentValue = (this.value || []).slice();
|
||||
const selected = (this.selected || []).slice();
|
||||
const index = currentValue.indexOf(data[this.nodeKey]);
|
||||
if (index === -1) {
|
||||
selected.push(node);
|
||||
currentValue.push(data[this.nodeKey]);
|
||||
this.$set(node, 'selected', true);
|
||||
} else {
|
||||
selected.splice(index, 1);
|
||||
currentValue.splice(index, 1);
|
||||
this.$set(node, 'selected', false);
|
||||
}
|
||||
this.selected = selected;
|
||||
this.$emit('input', currentValue);
|
||||
},
|
||||
|
||||
handleSingleSelect(data, node) {
|
||||
if (node.selected) return;
|
||||
const { label } = this.props;
|
||||
this.selectedLabel = data[label];
|
||||
this.$set(node, 'selected', true);
|
||||
this.$emit('input', data[this.nodeKey]);
|
||||
this.emitChange(data[this.nodeKey]);
|
||||
this.visible = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<div
|
||||
ref="dropdown"
|
||||
class="el-tree-select-dropdown el-popper"
|
||||
:class="[{ 'is-multiple': $parent.multiple }, popperClass]"
|
||||
:style="{ minWidth: minWidth }"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Popper from 'element-ui/src/utils/vue-popper';
|
||||
|
||||
export default {
|
||||
name: 'ElTreeSelectDropdown',
|
||||
|
||||
componentName: 'ElTreeSelectDropdown',
|
||||
|
||||
mixins: [Popper],
|
||||
|
||||
props: {
|
||||
placement: {
|
||||
default: 'bottom-start'
|
||||
},
|
||||
|
||||
boundariesPadding: {
|
||||
default: 0
|
||||
},
|
||||
|
||||
popperOptions: {
|
||||
default() {
|
||||
return {
|
||||
gpuAcceleration: false
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
visibleArrow: {
|
||||
default: true
|
||||
},
|
||||
|
||||
appendToBody: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
minWidth: ''
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
popperClass() {
|
||||
return this.$parent.popperClass;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$parent.inputWidth'() {
|
||||
this.minWidth = this.$parent.$el.getBoundingClientRect().width + 'px';
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.referenceElm = this.$parent.$refs.reference.$el;
|
||||
this.$parent.popperElm = this.popperElm = this.$el;
|
||||
this.$on('updatePopper', () => {
|
||||
if (this.$parent.visible) this.updatePopper();
|
||||
});
|
||||
this.$on('destroyPopper', this.destroyPopper);
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -211,7 +211,7 @@
|
|||
checkedKeys: store.getCheckedKeys(),
|
||||
halfCheckedNodes: store.getHalfCheckedNodes(),
|
||||
halfCheckedKeys: store.getHalfCheckedKeys(),
|
||||
});
|
||||
}, this.node);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -291,6 +291,16 @@
|
|||
this.treeItems[0] && this.treeItems[0].setAttribute('tabindex', 0);
|
||||
},
|
||||
|
||||
initFocusedItem(direction) {
|
||||
if (!this.treeItemArray.length) return;
|
||||
if (direction === 'next') {
|
||||
this.treeItemArray[0].focus();
|
||||
}
|
||||
if (direction === 'prev') {
|
||||
this.treeItemArray[this.treeItemArray.length - 1].focus();
|
||||
}
|
||||
},
|
||||
|
||||
handleKeydown(ev) {
|
||||
const currentItem = ev.target;
|
||||
if (currentItem.className.indexOf('el-tree-node') === -1) return;
|
||||
|
|
|
@ -89,6 +89,7 @@ import Empty from '../packages/empty/index.js';
|
|||
import Descriptions from '../packages/descriptions/index.js';
|
||||
import DescriptionsItem from '../packages/descriptions-item/index.js';
|
||||
import Result from '../packages/result/index.js';
|
||||
import TreeSelect from '../packages/tree-select/index.js';
|
||||
import locale from 'element-ui/src/locale';
|
||||
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
|
||||
|
||||
|
@ -177,6 +178,7 @@ const components = [
|
|||
Descriptions,
|
||||
DescriptionsItem,
|
||||
Result,
|
||||
TreeSelect,
|
||||
CollapseTransition
|
||||
];
|
||||
|
||||
|
@ -305,5 +307,6 @@ export default {
|
|||
Empty,
|
||||
Descriptions,
|
||||
DescriptionsItem,
|
||||
Result
|
||||
Result,
|
||||
TreeSelect
|
||||
};
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import { createTest, createVue, destroyVM } from '../util';
|
||||
import TreeSelect from 'packages/tree-select';
|
||||
|
||||
const data = [
|
||||
{
|
||||
value: 1,
|
||||
label: '一级 1',
|
||||
children: [
|
||||
{
|
||||
value: 11,
|
||||
label: '二级 1-1',
|
||||
children: [
|
||||
{
|
||||
value: 111,
|
||||
label: '三级 1-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
describe('TreeSelect', () => {
|
||||
const getTreeSelectVm = (configs = {}, options) => {
|
||||
['multiple', 'checkStrictly', 'showCheckbox'].forEach(config => {
|
||||
configs[config] = configs[config] || false;
|
||||
});
|
||||
const vm = createVue(Object.assign({
|
||||
template: `
|
||||
<el-tree-select
|
||||
v-model="value"
|
||||
:data="data"
|
||||
:multiple="multiple"
|
||||
:checkStrictly="checkStrictly"
|
||||
:showCheckbox="showCheckbox"
|
||||
/>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
value: '',
|
||||
multiple: configs.multiple,
|
||||
checkStrictly: configs.checkStrictly,
|
||||
showCheckbox: configs.showCheckbox
|
||||
};
|
||||
}
|
||||
}, options), true);
|
||||
return vm;
|
||||
};
|
||||
|
||||
let vm;
|
||||
afterEach(() => {
|
||||
destroyVM(vm);
|
||||
});
|
||||
|
||||
it('create', () => {
|
||||
vm = createTest(TreeSelect, true);
|
||||
expect(vm.$el).to.exist;
|
||||
});
|
||||
|
||||
it('render dropdown', async() => {
|
||||
vm = getTreeSelectVm();
|
||||
expect(vm.$el.querySelector('.el-tree')).to.exist;
|
||||
expect(vm.$el.querySelectorAll('.el-tree > .el-tree-node').length).to.equal(1);
|
||||
expect(vm.$el.querySelectorAll('.el-tree .el-tree-node').length).to.equal(3);
|
||||
});
|
||||
|
||||
it('default value', done => {
|
||||
vm = createVue({
|
||||
template: `
|
||||
<div>
|
||||
<el-tree-select
|
||||
v-model="value"
|
||||
:data="data"
|
||||
/>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
data: data,
|
||||
value: 111
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
setTimeout(() => {
|
||||
expect(vm.$el.querySelector('.el-input__inner').value).to.equal('三级 1-1');
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
it('disabled select', () => {
|
||||
vm = createTest(TreeSelect, { disabled: true, value: '' }, true);
|
||||
expect(vm.$el.querySelector('.el-input').classList.contains('is-disabled')).to.true;
|
||||
});
|
||||
});
|
|
@ -89,6 +89,7 @@ import { ElDescriptions } from './descriptions'
|
|||
import { ElDescriptionsItem } from './descriptions-item'
|
||||
import { ElResult } from './result'
|
||||
import { ElStatistic } from './statistic'
|
||||
import { ElTreeSelect } from './tree-select'
|
||||
|
||||
export interface InstallationOptions {
|
||||
locale: any,
|
||||
|
@ -380,3 +381,5 @@ export class Result extends ElResult {}
|
|||
|
||||
/** Statistic Component */
|
||||
export class Statistic extends ElStatistic {}
|
||||
/** TreeSelect Component */
|
||||
export class TreeSelect extends ElTreeSelect {}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
import { ElementUIComponent, ElementUIComponentSize } from "./component";
|
||||
|
||||
export interface TreeData {
|
||||
value?: any;
|
||||
label?: string;
|
||||
disabled?: boolean;
|
||||
isLeaf?: boolean;
|
||||
children?: TreeData[];
|
||||
}
|
||||
|
||||
export interface TreeProps {
|
||||
label: string;
|
||||
disabled: string;
|
||||
isLeaf: string;
|
||||
children: string;
|
||||
}
|
||||
|
||||
export interface QueryChangeHandler {
|
||||
/**
|
||||
* @param queryString Current value of the text input
|
||||
*/
|
||||
(queryString: string): void;
|
||||
}
|
||||
|
||||
/** TreeSelect Component */
|
||||
export declare class ElTreeSelect<V = any, D = TreeData> extends ElementUIComponent {
|
||||
/** The form input value */
|
||||
value: V | V[];
|
||||
|
||||
/** Tree data */
|
||||
data: D[];
|
||||
|
||||
/** Whether multiple-select is activated */
|
||||
multiple: boolean;
|
||||
|
||||
/** Whether Select is disabled */
|
||||
disabled: boolean;
|
||||
|
||||
/** Unique identity key name for value, required when value is an object */
|
||||
nodeKey: string;
|
||||
|
||||
/** Configuration options, see the following table */
|
||||
props: TreeProps;
|
||||
|
||||
/** Size of Input */
|
||||
size: ElementUIComponentSize;
|
||||
|
||||
/** Whether single select can be cleared */
|
||||
clearable: boolean;
|
||||
|
||||
/** The name attribute of select input */
|
||||
name: string;
|
||||
|
||||
/** Placeholder */
|
||||
placeholder: string;
|
||||
|
||||
/** Whether Select is filterable */
|
||||
filterable: boolean;
|
||||
|
||||
/** Custom filter method */
|
||||
filterMethod: QueryChangeHandler;
|
||||
|
||||
/** Whether to append the popper menu to body */
|
||||
popperAppendToBody: boolean;
|
||||
|
||||
/** Method for loading subtree data */
|
||||
load: (data: D, resolve: Function) => void;
|
||||
|
||||
/** Displayed text when data is empty */
|
||||
emptyText: string;
|
||||
|
||||
/** Horizontal indentation of nodes in adjacent levels in pixels */
|
||||
indent: number;
|
||||
|
||||
/** Whether checked state of a node not affects its father and child nodes when show-checkbox is true */
|
||||
checkStrictly: boolean;
|
||||
|
||||
/** Whether only one node among the same level can be expanded at one time */
|
||||
accordion: boolean;
|
||||
|
||||
/** Whether node is selectable */
|
||||
showCheckbox: boolean;
|
||||
|
||||
/**whether to collapse tags to a text when multiple selecting */
|
||||
collapseTags: boolean;
|
||||
|
||||
/** Whether Select is loading data from server */
|
||||
loading: boolean;
|
||||
|
||||
/** Method for loading subtree data */
|
||||
load: (data: D, resolve: Function) => void;
|
||||
|
||||
/** whether to lazy load leaf node, used with load attribute */
|
||||
lazy: boolean;
|
||||
|
||||
/** Whether to expand all nodes by default */
|
||||
defaultExpandAll: boolean;
|
||||
|
||||
/** Whether to expand father node when a child node is expanded */
|
||||
autoExpandParent: boolean;
|
||||
|
||||
/**
|
||||
* Focus the Input component
|
||||
*/
|
||||
focus(): void;
|
||||
|
||||
/**
|
||||
* Blur the Input component, and hide the dropdown
|
||||
*/
|
||||
blur(): void;
|
||||
}
|
Loading…
Reference in New Issue