feat(tree, tree-select): add label-field prop

This commit is contained in:
07akioni 2021-08-30 01:51:32 +08:00
parent 5f26ecf0e1
commit 2cd46a4890
16 changed files with 494 additions and 67 deletions

View File

@ -7,7 +7,8 @@
- `n-cascader` add `onUpdateValue` prop.
- `n-auto-complete` add `onUpdateValue` prop.
- `n-data-table`'s column's `renderFilterMenu` add `hide` params.
- `n-tree` & `n-tree-select` add `node-key` prop.
- `n-tree` & `n-tree-select` add `key-field` prop.
- `n-tree` & `n-tree-select` add `label-field` prop.
### Fixes

View File

@ -7,7 +7,8 @@
- `n-cascader` 新增 `onUpdateValue` 方法
- `n-auto-complete` 新增 `onUpdateValue` 方法
- `n-data-table` 的列的 `renderFilterMenu` 新增 hide 参数
- `n-tree``n-tree-select` 新增 `node-key` 属性
- `n-tree``n-tree-select` 新增 `key-field` 属性
- `n-tree``n-tree-select` 新增 `label-field` 属性
### Fixes

View File

@ -0,0 +1,142 @@
# Customize Key and Label Field
Various data would come from backend.
```html
<n-tree-select
:options="options"
default-value="Drive My Car"
label-field="whateverLabel"
key-field="whateverKey"
/>
```
```js
import { defineComponent } from 'vue'
export default defineComponent({
setup () {
return {
options: [
{
whateverLabel: 'Rubber Soul',
whateverKey: 'Rubber Soul',
children: [
{
whateverLabel:
"Everybody's Got Something to Hide Except Me and My Monkey",
whateverKey:
"Everybody's Got Something to Hide Except Me and My Monkey"
},
{
whateverLabel: 'Drive My Car',
whateverKey: 'Drive My Car',
disabled: true
},
{
whateverLabel: 'Norwegian Wood',
whateverKey: 'Norwegian Wood'
},
{
whateverLabel: "You Won't See",
whateverKey: "You Won't See",
disabled: true
},
{
whateverLabel: 'Nowhere Man',
whateverKey: 'Nowhere Man'
},
{
whateverLabel: 'Think For Yourself',
whateverKey: 'Think For Yourself'
},
{
whateverLabel: 'The Word',
whateverKey: 'The Word'
},
{
whateverLabel: 'Michelle',
whateverKey: 'Michelle',
disabled: true
},
{
whateverLabel: 'What goes on',
whateverKey: 'What goes on'
},
{
whateverLabel: 'Girl',
whateverKey: 'Girl'
},
{
whateverLabel: "I'm looking through you",
whateverKey: "I'm looking through you"
},
{
whateverLabel: 'In My Life',
whateverKey: 'In My Life'
},
{
whateverLabel: 'Wait',
whateverKey: 'Wait'
}
]
},
{
whateverLabel: 'Let It Be',
whateverKey: 'Let It Be Album',
children: [
{
whateverLabel: 'Two Of Us',
whateverKey: 'Two Of Us'
},
{
whateverLabel: 'Dig A Pony',
whateverKey: 'Dig A Pony'
},
{
whateverLabel: 'Across The Universe',
whateverKey: 'Across The Universe'
},
{
whateverLabel: 'I Me Mine',
whateverKey: 'I Me Mine'
},
{
whateverLabel: 'Dig It',
whateverKey: 'Dig It'
},
{
whateverLabel: 'Let It Be',
whateverKey: 'Let It Be'
},
{
whateverLabel: 'Maggie Mae',
whateverKey: 'Maggie Mae'
},
{
whateverLabel: "I've Got A Feeling",
whateverKey: "I've Got A Feeling"
},
{
whateverLabel: 'One After 909',
whateverKey: 'One After 909'
},
{
whateverLabel: 'The Long And Winding Road',
whateverKey: 'The Long And Winding Road'
},
{
whateverLabel: 'For You Blue',
whateverKey: 'For You Blue'
},
{
whateverLabel: 'Get Back',
whateverKey: 'Get Back'
}
]
}
]
}
}
})
```

View File

@ -6,6 +6,7 @@ It's said that 99% of the people can't distinguish it from cascader.
```demo
basic
custom-field
multiple
checkbox
filterable
@ -29,9 +30,10 @@ debug
| expanded-keys | `Array<string \| number>` | `undefined` | Expanded keys. |
| filterable | `boolean` | `false` | Whether the tree select is disabled. |
| filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | Filter function. |
| key-field | `string` | `'key'` | The key field in `TreeOption`. |
| label-field | `string` | `'label'` | The the label field in `TreeOption`. |
| max-tag-count | `number \| 'responsive'` | `undefined` | Max tag count to be shown in multiple mode. Set to `'responsive'` will keep all tags in the same row. |
| multiple | `boolean` | `false` | Whether to support multiple select. |
| node-key | `string` | `undefined` | Replace the key in `TreeSelectOption`. |
| options | `TreeSelectOption[]` | `[]` | Options. |
| placeholder | `string` | `'Please Select'` | Placeholder. |
| separator | `string` | `' / '` | Option value separator. |
@ -46,9 +48,9 @@ debug
### TreeSelectOption Properties
| Name | Type | Description |
| --------- | -------------------- | ------------------------------------ |
| key | `string \| number` | Key of the option. Should be unique. |
| label | `string` | Displayed content of the option. |
| children? | `TreeSelectOption[]` | Child options of the option. |
| disabled? | `boolean` | Whether to disabled the option. |
| Name | Type | Description |
| --- | --- | --- |
| key | `string \| number` | Key of the option. Should be unique. You can use `key-field` to customize the field name. |
| label | `string` | Displayed content of the option. You can use `label-field` to customize the field name. |
| children? | `TreeSelectOption[]` | Child options of the option. |
| disabled? | `boolean` | Whether to disabled the option. |

View File

@ -0,0 +1,142 @@
# 自定义 key 和 label 的字段
后端会传来各种各样的数据。
```html
<n-tree-select
:options="options"
default-value="Drive My Car"
label-field="whateverLabel"
key-field="whateverKey"
/>
```
```js
import { defineComponent } from 'vue'
export default defineComponent({
setup () {
return {
options: [
{
whateverLabel: 'Rubber Soul',
whateverKey: 'Rubber Soul',
children: [
{
whateverLabel:
"Everybody's Got Something to Hide Except Me and My Monkey",
whateverKey:
"Everybody's Got Something to Hide Except Me and My Monkey"
},
{
whateverLabel: 'Drive My Car',
whateverKey: 'Drive My Car',
disabled: true
},
{
whateverLabel: 'Norwegian Wood',
whateverKey: 'Norwegian Wood'
},
{
whateverLabel: "You Won't See",
whateverKey: "You Won't See",
disabled: true
},
{
whateverLabel: 'Nowhere Man',
whateverKey: 'Nowhere Man'
},
{
whateverLabel: 'Think For Yourself',
whateverKey: 'Think For Yourself'
},
{
whateverLabel: 'The Word',
whateverKey: 'The Word'
},
{
whateverLabel: 'Michelle',
whateverKey: 'Michelle',
disabled: true
},
{
whateverLabel: 'What goes on',
whateverKey: 'What goes on'
},
{
whateverLabel: 'Girl',
whateverKey: 'Girl'
},
{
whateverLabel: "I'm looking through you",
whateverKey: "I'm looking through you"
},
{
whateverLabel: 'In My Life',
whateverKey: 'In My Life'
},
{
whateverLabel: 'Wait',
whateverKey: 'Wait'
}
]
},
{
whateverLabel: 'Let It Be',
whateverKey: 'Let It Be Album',
children: [
{
whateverLabel: 'Two Of Us',
whateverKey: 'Two Of Us'
},
{
whateverLabel: 'Dig A Pony',
whateverKey: 'Dig A Pony'
},
{
whateverLabel: 'Across The Universe',
whateverKey: 'Across The Universe'
},
{
whateverLabel: 'I Me Mine',
whateverKey: 'I Me Mine'
},
{
whateverLabel: 'Dig It',
whateverKey: 'Dig It'
},
{
whateverLabel: 'Let It Be',
whateverKey: 'Let It Be'
},
{
whateverLabel: 'Maggie Mae',
whateverKey: 'Maggie Mae'
},
{
whateverLabel: "I've Got A Feeling",
whateverKey: "I've Got A Feeling"
},
{
whateverLabel: 'One After 909',
whateverKey: 'One After 909'
},
{
whateverLabel: 'The Long And Winding Road',
whateverKey: 'The Long And Winding Road'
},
{
whateverLabel: 'For You Blue',
whateverKey: 'For You Blue'
},
{
whateverLabel: 'Get Back',
whateverKey: 'Get Back'
}
]
}
]
}
}
})
```

View File

@ -6,6 +6,7 @@
```demo
basic
custom-field
multiple
checkbox
filterable
@ -29,10 +30,11 @@ debug
| expanded-keys | `Array<string \| number>` | `undefined` | 展开节点的 key |
| filterable | `boolean` | `false` | 是否可过滤 |
| filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | 过滤器函数 |
| key-field | `string` | `'key'` | `TreeOption` 中的 key 字段名 |
| label-field | `string` | `'label'` | 替代 `TreeOption` 中的 label 字段名 |
| leaf-only | `boolean` | `false` | 是否开启仅末层树节点可选 |
| max-tag-count | `number \| 'responsive'` | `undefined` | 多选时最多直接显示多少选项,设为 `'responsive'` 会保证最多一行 |
| multiple | `boolean` | `false` | 是否支持多选 |
| node-key | `string` | `undefined` | 替代 `TreeSelectOption` 中的 key |
| options | `TreeSelectOption[]` | `[]` | 选项 |
| placeholder | `string` | `'请选择'` | 占位信息 |
| separator | `string` | `' / '` | 数据分隔符 |
@ -47,9 +49,9 @@ debug
### TreeSelectOption Properties
| 名称 | 类型 | 说明 |
| --------- | -------------------- | -------------------- |
| key | `string \| number` | 选项的 key需要唯一 |
| label | `string` | 选项的显示内容 |
| children? | `TreeSelectOption[]` | 节点的子选项 |
| disabled? | `boolean` | 是否禁用选项 |
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| key | `string \| number` | 选项的 key需要唯一,可使用 `key-field` 修改字段名 |
| label | `string` | 选项的显示内容,可使用 `label-field` 修改字段名 |
| children? | `TreeSelectOption[]` | 节点的子选项 |
| disabled? | `boolean` | 是否禁用选项 |

View File

@ -61,7 +61,6 @@ const props = {
type: Boolean,
default: true
},
nodeKey: String,
cascade: Boolean,
checkable: Boolean,
clearable: Boolean,
@ -154,6 +153,17 @@ export default defineComponent({
const controlledShowRef = toRef(props, 'show')
const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef)
const patternRef = ref('')
const mergedFilterRef = computed(() => {
const { filter } = props
if (filter) return filter
const { labelField } = props
return (pattern: string, node: TreeSelectOption): boolean => {
if (!pattern.length) return true
return ((node as any)[labelField] as string)
.toLowerCase()
.includes(pattern.toLowerCase())
}
})
const filteredTreeInfoRef = computed<{
filteredTree: TreeSelectOption[]
highlightKeySet: Set<Key> | undefined
@ -167,26 +177,31 @@ export default defineComponent({
}
}
const { value: pattern } = patternRef
if (!pattern.length || !props.filter) {
if (!pattern.length || !mergedFilterRef.value) {
return {
filteredTree: props.options,
highlightKeySet: undefined,
expandedKeys: undefined
}
}
return filterTree(props.options, props.filter, pattern)
return filterTree(
props.options,
mergedFilterRef.value,
pattern,
props.keyField
)
})
// used to resolve selected options
const dataTreeMateRef = computed(() =>
createTreeMate<TreeSelectOption>(
props.options,
createTreeMateOptions(props.nodeKey)
createTreeMateOptions(props.keyField)
)
)
const displayTreeMateRef = computed(() =>
createTreeMate<TreeSelectOption>(
filteredTreeInfoRef.value.filteredTree,
createTreeMateOptions(props.nodeKey)
createTreeMateOptions(props.keyField)
)
)
const { value: initMergedValue } = mergedValueRef
@ -244,7 +259,7 @@ export default defineComponent({
}
})
const selectedOptionRef = computed(() => {
const { multiple, showPath, separator } = props
const { multiple, showPath, separator, labelField } = props
if (multiple) return null
const { value: mergedValue } = mergedValueRef
if (!Array.isArray(mergedValue) && mergedValue !== null) {
@ -255,9 +270,10 @@ export default defineComponent({
? treeOption2SelectOptionWithPath(
tmNode,
treeMate.getPath(mergedValue).treeNodePath,
separator
separator,
labelField
)
: treeOption2SelectOption(tmNode)
: treeOption2SelectOption(tmNode, labelField)
}
}
return null
@ -269,6 +285,7 @@ export default defineComponent({
if (Array.isArray(mergedValue)) {
const res: SelectBaseOption[] = []
const { value: treeMate } = dataTreeMateRef
const { keyField, labelField } = props
mergedValue.forEach((value) => {
const tmNode = treeMate.getNode(value)
if (tmNode !== null) {
@ -277,9 +294,10 @@ export default defineComponent({
? treeOption2SelectOptionWithPath(
tmNode,
treeMate.getPath(value).treeNodePath,
separator
separator,
keyField
)
: treeOption2SelectOption(tmNode)
: treeOption2SelectOption(tmNode, labelField)
)
}
})
@ -694,6 +712,7 @@ export default defineComponent({
animated={false}
data={filteredTreeInfo.filteredTree}
cancelable={multiple}
labelField={this.labelField}
theme={mergedTheme.peers.Tree}
themeOverrides={
mergedTheme.peerOverrides.Tree

View File

@ -3,11 +3,13 @@ import { Key } from '../../tree/src/interface'
import { TreeSelectTmNode, TreeSelectOption } from './interface'
export function treeOption2SelectOption (
tmNode: TreeSelectTmNode
tmNode: TreeSelectTmNode,
labelField: string
): SelectBaseOption {
const { rawNode } = tmNode
return {
...rawNode,
label: (rawNode as any)[labelField] as string,
value: tmNode.key
}
}
@ -15,20 +17,22 @@ export function treeOption2SelectOption (
export function treeOption2SelectOptionWithPath (
tmNode: TreeSelectTmNode,
path: TreeSelectTmNode[],
separator: string
separator: string,
labelField: string
): SelectBaseOption {
const { rawNode } = tmNode
return {
...rawNode,
value: tmNode.key,
label: path.map((v) => v.rawNode.label).join(separator)
label: path.map((v) => v.rawNode[labelField]).join(separator)
}
}
export function filterTree (
tree: TreeSelectOption[],
filter: (pattern: string, v: TreeSelectOption) => boolean,
pattern: string
pattern: string,
keyField: string
): {
filteredTree: TreeSelectOption[]
expandedKeys: Key[]
@ -44,10 +48,10 @@ export function filterTree (
t.forEach((n) => {
path.push(n)
if (filter(pattern, n)) {
visitedTailKeys.add(n.key)
highlightKeySet.add(n.key)
visitedTailKeys.add((n as any)[keyField] as Key)
highlightKeySet.add((n as any)[keyField] as Key)
for (let i = path.length - 2; i >= 0; --i) {
const { key } = path[i]
const key: Key = (path[i] as any)[keyField]
if (!visitedNonTailKeys.has(key)) {
visitedNonTailKeys.add(key)
if (visitedTailKeys.has(key)) {
@ -67,7 +71,7 @@ export function filterTree (
visit(tree)
function build (t: TreeSelectOption[], sibs: TreeSelectOption[]): void {
t.forEach((n) => {
const { key } = n
const key = (n as any)[keyField] as Key
const isVisitedTail = visitedTailKeys.has(key)
const isVisitedNonTail = visitedNonTailKeys.has(key)
if (!isVisitedTail && !isVisitedNonTail) return
@ -78,7 +82,7 @@ export function filterTree (
sibs.push(n)
} else {
// It it is not visited path tail, use cloned node
expandedKeys.push(n.key)
expandedKeys.push(key)
const clonedNode = { ...n, children: [] }
sibs.push(clonedNode)
build(children, clonedNode.children)

View File

@ -0,0 +1,46 @@
# Customize Key and Label Field
Various data would come from backend.
```html
<n-tree
block-line
:data="data"
:default-expanded-keys="defaultExpandedKeys"
key-field="whateverKey"
label-field="whateverLabel"
selectable
/>
```
```js
import { defineComponent, ref } from 'vue'
function createData (level = 4, baseKey = '') {
if (!level) return undefined
return Array.apply(null, { length: 6 - level }).map((_, index) => {
const key = '' + baseKey + level + index
return {
whateverLabel: createLabel(level),
whateverKey: key,
children: createData(level - 1, key)
}
})
}
function createLabel (level) {
if (level === 4) return 'Out of Tao, One is born'
if (level === 3) return 'Out of One, Two'
if (level === 2) return 'Out of Two, Three'
if (level === 1) return 'Out of Three, the created universe'
}
export default defineComponent({
setup () {
return {
data: createData(),
defaultExpandedKeys: ref(['40', '41'])
}
}
})
```

View File

@ -8,6 +8,7 @@ What's more, not only biology, I forget balanced tree everytime after I revise i
```demo
basic
custom-field
cascade
multiple
filter
@ -41,9 +42,10 @@ batch-render
| expand-on-dragenter | `boolean` | `true` | Whether to expand nodes after dragenter. |
| expanded-keys | `Array<string \| number>` | `undefined` | If set, expanded status will work in controlled manner. |
| filter | `(node: TreeOption) => boolean` | `undefined` | A simple string based filter. |
| key-field | `string` | `'key'` | The key field in `TreeOption`. |
| label-field | `string` | `'label'` | The the label field in `TreeOption`. |
| leaf-only | `boolean` | `false` | Whether to open or not, only the bottom tree node is optional. |
| multiple | `boolean` | `false` | Whether to allow multiple selection of nodes. |
| node-key | `string` | `undefined` | Replace the key in `TreeOption`. |
| on-load | `(node: TreeOption) => Promise<void>` | `undefined` | Callback function for asynchronously loading data. |
| pattern | `string` | `''` | What to search by default. |
| remote | `boolean` | `false` | Whether to load nodes async. It should work with `on-load`. |
@ -66,8 +68,8 @@ batch-render
| Name | Type | Description |
| --- | --- | --- |
| key | `string \| number` | Key of the node, should be unique. |
| label | `string` | Label of the node. |
| key | `string \| number` | Key of the node, should be unique. You can use `key-field` to customize the field name. |
| label | `string` | Label of the node. You can use `label-field` to customize the field name. |
| checkboxDisabled? | `boolean` | Whether the checkbox is disabled. |
| children? | `TreeOption[]` | Child nodes of the node. |
| disabled? | `boolean` | Whether the node is disabled. |

View File

@ -0,0 +1,46 @@
# 自定义 key 和 label 的字段
后端会传来各种各样的数据。
```html
<n-tree
block-line
:data="data"
:default-expanded-keys="defaultExpandedKeys"
key-field="whateverKey"
label-field="whateverLabel"
selectable
/>
```
```js
import { defineComponent, ref } from 'vue'
function createData (level = 4, baseKey = '') {
if (!level) return undefined
return Array.apply(null, { length: 6 - level }).map((_, index) => {
const key = '' + baseKey + level + index
return {
whateverLabel: createLabel(level),
whateverKey: key,
children: createData(level - 1, key)
}
})
}
function createLabel (level) {
if (level === 4) return '道生一'
if (level === 3) return '一生二'
if (level === 2) return '二生三'
if (level === 1) return '三生万物'
}
export default defineComponent({
setup () {
return {
data: createData(),
defaultExpandedKeys: ref(['40', '41'])
}
}
})
```

View File

@ -8,6 +8,7 @@
```demo
basic
custom-field
cascade
multiple
filter
@ -41,9 +42,10 @@ batch-render
| expand-on-dragenter | `boolean` | `true` | 是否在拖入后展开节点 |
| expanded-keys | `Array<string \| number>` | `undefined` | 如果设定则展开受控 |
| filter | `(node: TreeOption) => boolean` | `undefined` | 一个简单的字符串过滤算法 |
| key-field | `string` | `'key'` | `TreeOption` 中的 key 字段名 |
| label-field | `string` | `'label'` | 替代 `TreeOption` 中的 label 字段名 |
| leaf-only | `boolean` | `false` | 是否开启仅末层树节点可选 |
| multiple | `boolean` | `false` | 是否允许节点多选 |
| node-key | `string` | `undefined` | 替代 `TreeOption` 中的 key |
| on-load | `(node: TreeOption) => Promise<void>` | `undefined` | 异步加载数据的回调函数 |
| pattern | `string` | `''` | 默认搜索的内容 |
| remote | `boolean` | `false` | 是否异步获取选项,和 `onLoad` 配合 |
@ -66,8 +68,8 @@ batch-render
| 名称 | 类型 | 说明 |
| --- | --- | --- |
| key | `string \| number` | 节点的 `key`,需要唯一 |
| label | `string` | 节点的内容 |
| key | `string \| number` | 节点的 `key`,需要唯一,可使用 `key-field` 修改字段名 |
| label | `string` | 节点的内容,可使用 `label-field` 修改字段名 |
| checkboxDisabled? | `boolean` | 是否禁用节点的 `checkbox` |
| children? | `TreeOption[]` | 节点的子节点 |
| disabled? | `boolean` | 是否禁用节点 |

View File

@ -31,7 +31,7 @@ import type { ScrollbarInst } from '../../scrollbar'
import { treeLight } from '../styles'
import type { TreeTheme } from '../styles'
import NTreeNode from './TreeNode'
import { keysWithFilter, emptyImage, defaultFilter } from './utils'
import { keysWithFilter, emptyImage } from './utils'
import { useKeyboard } from './keyboard'
import {
TreeDragInfo,
@ -62,11 +62,11 @@ import style from './styles/index.cssr'
const ITEM_SIZE = 30 // 24 + 3 + 3
export function createTreeMateOptions<T> (
nodeKey: string | undefined
keyField: string
): TreeMateOptions<T, T, T> {
return {
getKey (node: T) {
return nodeKey ? (node as any)[nodeKey] : (node as any).key
return (node as any)[keyField]
},
getDisabled (node: T) {
return !!((node as any).disabled || (node as any).checkboxDisabled)
@ -75,12 +75,17 @@ export function createTreeMateOptions<T> (
}
export const treeSharedProps = {
filter: {
type: Function as PropType<(pattern: string, node: TreeOption) => boolean>,
default: defaultFilter
},
filter: Function as PropType<(pattern: string, node: TreeOption) => boolean>,
defaultExpandAll: Boolean,
expandedKeys: Array as PropType<Key[]>,
keyField: {
type: String,
default: 'key'
},
labelField: {
type: String,
default: 'label'
},
defaultExpandedKeys: {
type: Array as PropType<Key[]>,
default: () => []
@ -107,7 +112,6 @@ const treeProps = {
type: Boolean,
default: true
},
nodeKey: String,
checkable: Boolean,
draggable: Boolean,
blockNode: Boolean,
@ -232,7 +236,7 @@ export default defineComponent({
: computed(() =>
createTreeMate<TreeOption>(
props.data,
createTreeMateOptions(props.nodeKey)
createTreeMateOptions(props.keyField)
)
)
const dataTreeMateRef = props.internalDataTreeMate
@ -314,6 +318,18 @@ export default defineComponent({
return droppingNode.parent
})
const mergedFilterRef = computed(() => {
const { filter } = props
if (filter) return filter
const { labelField } = props
return (pattern: string, node: TreeOption): boolean => {
if (!pattern.length) return true
return ((node as any)[labelField] as string)
.toLowerCase()
.includes(pattern.toLowerCase())
}
})
// shallow watch data
watch(
toRef(props, 'data'),
@ -329,7 +345,12 @@ export default defineComponent({
watch(toRef(props, 'pattern'), (value) => {
if (value) {
const { expandedKeys: expandedKeysAfterChange, highlightKeySet } =
keysWithFilter(props.data, props.pattern, props.filter)
keysWithFilter(
props.data,
props.pattern,
props.keyField,
mergedFilterRef.value
)
uncontrolledHighlightKeySetRef.value = highlightKeySet
doUpdateExpandedKeys(expandedKeysAfterChange)
} else {
@ -1013,6 +1034,7 @@ export default defineComponent({
renderLabelRef: toRef(props, 'renderLabel'),
renderPrefixRef: toRef(props, 'renderPrefix'),
renderSuffixRef: toRef(props, 'renderSuffix'),
labelFieldRef: toRef(props, 'labelField'),
handleSwitcherClick,
handleDragEnd,
handleDragEnter,

View File

@ -9,10 +9,7 @@ export default defineComponent({
type: String,
required: true
},
disabled: {
type: Boolean,
default: false
},
disabled: Boolean,
checked: Boolean,
selected: Boolean,
onClick: Function as PropType<(e: MouseEvent) => void>,
@ -23,7 +20,7 @@ export default defineComponent({
}
},
setup (props) {
const { renderLabelRef, renderPrefixRef, renderSuffixRef } =
const { renderLabelRef, renderPrefixRef, renderSuffixRef, labelFieldRef } =
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
inject(treeInjectionKey)!
const selfRef = ref<HTMLElement | null>(null)
@ -39,12 +36,14 @@ export default defineComponent({
renderLabel: renderLabelRef,
renderPrefix: renderPrefixRef,
renderSuffix: renderSuffixRef,
labelField: labelFieldRef,
handleClick
}
},
render () {
const {
clsPrefix,
labelField,
checked = false,
selected = false,
renderLabel,
@ -54,7 +53,7 @@ export default defineComponent({
onDragstart,
tmNode: {
rawNode,
rawNode: { prefix, label, suffix }
rawNode: { prefix, suffix, [labelField]: label }
}
} = this
return (

View File

@ -6,8 +6,8 @@ import type { TreeTheme } from '../styles'
export type Key = string | number
export interface TreeOptionBase {
key: Key
label: string
key?: Key
label?: string
checkboxDisabled?: boolean
disabled?: boolean
isLeaf?: boolean
@ -99,6 +99,7 @@ export interface TreeInjection {
renderLabelRef: Ref<RenderLabel | undefined>
renderPrefixRef: Ref<RenderPrefix | undefined>
renderSuffixRef: Ref<RenderSuffix | undefined>
labelFieldRef: Ref<string>
handleSwitcherClick: (node: TreeNode<TreeOption>) => void
handleSelect: (node: TreeNode<TreeOption>) => void
handleCheck: (node: TreeNode<TreeOption>, checked: boolean) => void

View File

@ -15,6 +15,7 @@ function traverse (
export function keysWithFilter (
nodes: TreeOption[],
pattern: string,
keyField: string,
filter: (pattern: string, node: TreeOption) => boolean
): {
expandedKeys: Key[]
@ -28,10 +29,10 @@ export function keysWithFilter (
(node) => {
path.push(node)
if (filter(pattern, node)) {
highlightKeySet.add(node.key)
highlightKeySet.add((node as any)[keyField])
for (let i = path.length - 2; i >= 0; --i) {
if (!keys.has(path[i].key)) {
keys.add(path[i].key)
if (!keys.has((path[i] as any)[keyField])) {
keys.add((path[i] as any)[keyField])
} else {
return
}
@ -55,9 +56,4 @@ if (typeof window !== 'undefined') {
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
}
export const defaultFilter = (pattern: string, node: TreeOption): boolean => {
if (!pattern.length) return true
return node.label.toLowerCase().includes(pattern.toLowerCase())
}
export { emptyImage }