From 60448314c2a6d873b69202a2d515b9561fce08a3 Mon Sep 17 00:00:00 2001 From: zoomdong <1344492820@qq.com> Date: Sat, 7 Aug 2021 20:27:10 +0800 Subject: [PATCH] feat(tree-select): support showPath (#805) * feat: treeSelect support showPath * chore: add CHANGELOG * chore: add test case * chore: update doc * chore: update code * chore: update type * chore: upadte code * chore: add dots * chore: adjust code Co-authored-by: 07akioni <07akioni2@gmail.com> --- CHANGELOG.en-US.md | 3 +- CHANGELOG.zh-CN.md | 1 + .../demos/enUS/index.demo-entry.md | 2 + src/tree-select/demos/zhCN/debug.demo.md | 5 +- .../demos/zhCN/index.demo-entry.md | 2 + src/tree-select/src/TreeSelect.tsx | 46 ++++++++++++++++--- src/tree-select/src/utils.ts | 12 +++++ src/tree-select/tests/TreeSelect.spec.ts | 42 +++++++++++++++++ 8 files changed, 105 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 786cfabdb..cada5c6c9 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -4,7 +4,8 @@ ### Feats -- `n-message-provider` add `closable` props, closes [#795](https://github.com/TuSimple/naive-ui/issues/795). +- `n-message-provider` add `closable` prop, closes [#795](https://github.com/TuSimple/naive-ui/issues/795). +- `n-tree-select` add `showPath` prop, closes[#625](https://github.com/TuSimple/naive-ui/issues/623). - `n-layout` add `sider-placement` prop, closes [#566](https://github.com/TuSimple/naive-ui/issues/566). ### Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 18a111ea7..e93f7351b 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -5,6 +5,7 @@ ### Feats - `n-message-provider` 新增 `closable` 属性,关闭 [#795](https://github.com/TuSimple/naive-ui/issues/795) +- `n-tree-select` 新增 `showPath` 属性,关闭[#625](https://github.com/TuSimple/naive-ui/issues/623) - `n-layout` 增加 `sider-placement` 属性,关闭 [#566](https://github.com/TuSimple/naive-ui/issues/566) ### Fixes diff --git a/src/tree-select/demos/enUS/index.demo-entry.md b/src/tree-select/demos/enUS/index.demo-entry.md index 28da095dd..4b848efc8 100644 --- a/src/tree-select/demos/enUS/index.demo-entry.md +++ b/src/tree-select/demos/enUS/index.demo-entry.md @@ -33,6 +33,8 @@ debug | multiple | `boolean` | `false` | Whether to support multiple select. | | options | `TreeSelectOption[]` | `[]` | Options. | | placeholder | `string` | `'Please Select'` | Placeholder. | +| separator | `string` | `' / '` | Option value separator. | +| show-path | `boolean` | `false` | Whether to show path in selector. | | size | `'small' \| 'medium' \| 'large'` | `'medium'` | Component size. | | value | `string \| number \| Array \| null>` | `undefined` | Selected key (or keys when multiple). | | virtual-scroll | `boolean` | `true` | Whether to enable virtual scroll. | diff --git a/src/tree-select/demos/zhCN/debug.demo.md b/src/tree-select/demos/zhCN/debug.demo.md index b6d5585fd..4410d55dc 100644 --- a/src/tree-select/demos/zhCN/debug.demo.md +++ b/src/tree-select/demos/zhCN/debug.demo.md @@ -7,6 +7,7 @@ Checkable Cascade Filterable + ShowPath ``` @@ -41,7 +43,8 @@ export default defineComponent({ checkable: ref(false), cascade: ref(false), filterable: ref(false), - options: createData() + options: createData(), + showPath: ref(false) } } }) diff --git a/src/tree-select/demos/zhCN/index.demo-entry.md b/src/tree-select/demos/zhCN/index.demo-entry.md index 9d8859691..453b342c1 100644 --- a/src/tree-select/demos/zhCN/index.demo-entry.md +++ b/src/tree-select/demos/zhCN/index.demo-entry.md @@ -34,6 +34,8 @@ debug | multiple | `boolean` | `false` | 是否支持多选 | | options | `TreeSelectOption[]` | `[]` | 选项 | | placeholder | `string` | `'请选择'` | 占位信息 | +| separator | `string` | `' / '` | 数据分隔符 | +| show-path | `boolean` | `false` | 是否在选择器中显示选项路径 | | size | `'small' \| 'medium' \| 'large'` | `'medium'` | 组件尺寸 | | value | `string \| number \| Array \| null>` | `undefined` | 选中的 key | | virtual-scroll | `boolean` | `true` | 是否开启虚拟滚动 | diff --git a/src/tree-select/src/TreeSelect.tsx b/src/tree-select/src/TreeSelect.tsx index 9e4fa210d..024cec323 100644 --- a/src/tree-select/src/TreeSelect.tsx +++ b/src/tree-select/src/TreeSelect.tsx @@ -48,7 +48,11 @@ import type { Value } from './interface' import { treeSelectInjectionKey } from './interface' -import { treeOption2SelectOption, filterTree } from './utils' +import { + treeOption2SelectOption, + filterTree, + treeOption2SelectOptionWithPath +} from './utils' import style from './styles/index.cssr' const props = { @@ -79,6 +83,11 @@ const props = { leafOnly: Boolean, maxTagCount: [String, Number] as PropType, multiple: Boolean, + showPath: Boolean, + separator: { + type: String, + default: ' / ' + }, options: { type: Array as PropType, default: () => [] @@ -231,23 +240,48 @@ export default defineComponent({ } }) const selectedOptionRef = computed(() => { - if (props.multiple) return null + const { multiple, showPath, separator } = props + if (multiple) return null const { value: mergedValue } = mergedValueRef if (!Array.isArray(mergedValue) && mergedValue !== null) { - const tmNode = dataTreeMateRef.value.getNode(mergedValue) - if (tmNode !== null) return treeOption2SelectOption(tmNode.rawNode) + const { value: treeMate } = dataTreeMateRef + const tmNode = treeMate.getNode(mergedValue) + if (tmNode !== null) { + return showPath + ? treeOption2SelectOptionWithPath( + tmNode.rawNode, + treeMate + .getPath(mergedValue) + .treeNodePath.map(({ rawNode }) => rawNode.label), + separator + ) + : treeOption2SelectOption(tmNode.rawNode) + } } return null }) const selectedOptionsRef = computed(() => { - if (!props.multiple) return null + const { multiple, showPath, separator } = props + if (!multiple) return null const { value: mergedValue } = mergedValueRef if (Array.isArray(mergedValue)) { const res: SelectBaseOption[] = [] const { value: treeMate } = dataTreeMateRef mergedValue.forEach((value) => { const tmNode = treeMate.getNode(value) - if (tmNode !== null) res.push(treeOption2SelectOption(tmNode.rawNode)) + if (tmNode !== null) { + res.push( + showPath + ? treeOption2SelectOptionWithPath( + tmNode.rawNode, + treeMate + .getPath(value) + .treeNodePath.map(({ rawNode }) => rawNode.label), + separator + ) + : treeOption2SelectOption(tmNode.rawNode) + ) + } }) return res } diff --git a/src/tree-select/src/utils.ts b/src/tree-select/src/utils.ts index edbc0c98d..8100ab2a8 100644 --- a/src/tree-select/src/utils.ts +++ b/src/tree-select/src/utils.ts @@ -11,6 +11,18 @@ export function treeOption2SelectOption ( } } +export function treeOption2SelectOptionWithPath ( + treeOpt: TreeSelectOption, + treeNodePath: Key[], + separator: string +): SelectBaseOption { + return { + disabled: treeOpt.disabled, + value: treeOpt.key, + label: treeNodePath.join(separator) + } +} + export function filterTree ( tree: TreeSelectOption[], filter: (pattern: string, v: TreeSelectOption) => boolean, diff --git a/src/tree-select/tests/TreeSelect.spec.ts b/src/tree-select/tests/TreeSelect.spec.ts index 93db6dced..612e31624 100644 --- a/src/tree-select/tests/TreeSelect.spec.ts +++ b/src/tree-select/tests/TreeSelect.spec.ts @@ -29,4 +29,46 @@ describe('n-tree-select', () => { } }) }) + it('should show all path when set showPath', async () => { + const wrapper = mount(NTreeSelect, { + props: { + options: [ + { + label: '1', + key: '1', + children: [ + { + label: '1-1', + key: '1-1' + }, + { + label: '1-2', + key: '1-2' + } + ] + } + ], + showPath: true, + defaultValue: '1-2' + } + }) + expect(wrapper.find('.n-base-selection-label__input').exists()).toBe(true) + expect(wrapper.find('.n-base-selection-label__input').text()).toBe( + '1 / 1-2' + ) + + await wrapper.setProps({ showPath: false }) + expect(wrapper.find('.n-base-selection-label__input').exists()).toBe(true) + expect(wrapper.find('.n-base-selection-label__input').text()).toBe('1-2') + + await wrapper.setProps({ + showPath: true, + defaultValue: '1-1', + separator: ' | ' + }) + expect(wrapper.find('.n-base-selection-label__input').exists()).toBe(true) + expect(wrapper.find('.n-base-selection-label__input').text()).toBe( + '1 | 1-2' + ) + }) })