From 18395963e69e93a68aa430cfa1421af4017b46fe Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Oct 2021 16:27:59 +0800 Subject: [PATCH 1/3] feat(n-cascader): provide all top Key values in callback function --- CHANGELOG.en-US.md | 4 ++ CHANGELOG.zh-CN.md | 4 ++ src/cascader/demos/enUS/index.demo-entry.md | 2 +- src/cascader/demos/zhCN/index.demo-entry.md | 2 +- src/cascader/src/Cascader.tsx | 43 ++++++++++++++------- src/cascader/src/utils.ts | 17 +++++++- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 59fb6e66273..475d9b08c43 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -6,6 +6,10 @@ - Fix `n-menu`'s incorrect warning on `default-expanded-keys`. +### Feats + +- `n-cascader` provide all top Key values in `update:value` callback function,closes [#1235](https://github.com/TuSimple/naive-ui/issues/1235). + ## 2.19.5 (2021-10-07) ### Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index d5bb9c52b25..da7ee2d29e9 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -6,6 +6,10 @@ - 修复 `n-menu` 对于 `default-expanded-keys` 的错误警报 +### Feats + +- `n-cascader` 值改变时回调函数提供上层节点的全部 key 值,关闭 [#1235](https://github.com/TuSimple/naive-ui/issues/1235) + ## 2.19.5 (2021-10-07) ### Fixes diff --git a/src/cascader/demos/enUS/index.demo-entry.md b/src/cascader/demos/enUS/index.demo-entry.md index 4694773b2e8..3b514a78272 100644 --- a/src/cascader/demos/enUS/index.demo-entry.md +++ b/src/cascader/demos/enUS/index.demo-entry.md @@ -47,7 +47,7 @@ custom-field | on-blur | `() => void` | `undefined` | Callback on blurred. | | on-focus | `() => void` | `undefined` | Callback on focused. | | on-load | `(option: CascaderOption) => Promise` | `undefined` | Callback when a node is loaded. Set `option.children` in the returned promise. Loading will stop after the promise is resolved or rejected. | -| on-update:value | `(value: string \| number \| Array \| null, option: CascaderOption \| Array \| null) => void` | `undefined` | Callback executed when the value changes. | +| on-update:value | `(value: string \| number \| Array \| null, option: CascaderOption \| Array \| null, pathValues: Array \| Array> \| null) => void` | `undefined` | Callback executed when the value changes. | #### CascaderOption Properties diff --git a/src/cascader/demos/zhCN/index.demo-entry.md b/src/cascader/demos/zhCN/index.demo-entry.md index fbf82603989..d3fee24170f 100644 --- a/src/cascader/demos/zhCN/index.demo-entry.md +++ b/src/cascader/demos/zhCN/index.demo-entry.md @@ -47,7 +47,7 @@ custom-field | on-blur | `() => void` | `undefined` | 用户 blur 时执行的回调 | | on-focus | `() => void` | `undefined` | 用户 focus 时执行的回调 | | on-load | `(option: CascaderOption) => Promise` | `undefined` | 在点击未加载完成节点时的回调,在返回的 promise 中设定 `option.children`,在返回的 promise resolve 或 reject 之后完成加载 | -| on-update:value | `(value: string \| number \| Array \| null, option: CascaderOption \| Array \| null) => void` | `undefined` | 值改变时执行的回调 | +| on-update:value | `(value: string \| number \| Array \| null, option: CascaderOption \| Array \| null, pathValues: Array \| Array> \| null) => void` | `undefined` | 值改变时执行的回调 | #### CascaderOption Properties diff --git a/src/cascader/src/Cascader.tsx b/src/cascader/src/Cascader.tsx index 919c46fbe68..33688192c1b 100644 --- a/src/cascader/src/Cascader.tsx +++ b/src/cascader/src/Cascader.tsx @@ -29,7 +29,7 @@ import { call, useAdjustedTo, warnOnce } from '../../_utils' import type { ExtractPublicPropTypes, MaybeArray } from '../../_utils' import { cascaderLight } from '../styles' import type { CascaderTheme } from '../styles' -import { getPathLabel } from './utils' +import { getPathLabel, getPathValues } from './utils' import CascaderMenu from './CascaderMenu' import CascaderSelectMenu from './CascaderSelectMenu' import { @@ -255,7 +255,8 @@ export default defineComponent({ } function doUpdateValue ( value: Value | null, - option: CascaderOption | null | Array + option: CascaderOption | null | Array, + pathValues: null | Array | Array> ): void { const { onUpdateValue, @@ -263,11 +264,11 @@ export default defineComponent({ onChange } = props const { nTriggerFormInput, nTriggerFormChange } = formItem - if (onUpdateValue) call(onUpdateValue as OnUpdateValueImpl, value, option) + if (onUpdateValue) { call(onUpdateValue as OnUpdateValueImpl, value, option, pathValues) } if (_onUpdateValue) { - call(_onUpdateValue as OnUpdateValueImpl, value, option) + call(_onUpdateValue as OnUpdateValueImpl, value, option, pathValues) } - if (onChange) call(onChange as OnUpdateValueImpl, value, option) + if (onChange) { call(onChange as OnUpdateValueImpl, value, option, pathValues) } uncontrolledValueRef.value = value nTriggerFormInput() nTriggerFormChange() @@ -279,7 +280,7 @@ export default defineComponent({ hoverKeyRef.value = key } function doCheck (key: Key): boolean { - const { cascade, multiple, filterable } = props + const { cascade, multiple, filterable, valueField } = props const { value: { check, getNode } } = treeMateRef @@ -293,6 +294,10 @@ export default defineComponent({ checkedKeys, checkedKeys.map( (checkedKey) => getNode(checkedKey)?.rawNode || null + ), + checkedKeys.map( + (checkedKey) => + getPathValues(getNode(checkedKey), valueField) || null ) ) if (filterable) focusSelectionInput() @@ -314,19 +319,27 @@ export default defineComponent({ if (mergedCheckStrategyRef.value === 'child') { const tmNode = getNode(key) if (tmNode?.isLeaf) { - doUpdateValue(key, tmNode.rawNode) + doUpdateValue( + key, + tmNode.rawNode, + getPathValues(tmNode, valueField) + ) } else { return false } } else { const tmNode = getNode(key) - doUpdateValue(key, tmNode?.rawNode || null) + doUpdateValue( + key, + tmNode?.rawNode || null, + getPathValues(tmNode, valueField) + ) } } return true } function doUncheck (key: Key): void { - const { cascade, multiple } = props + const { cascade, multiple, valueField } = props if (multiple) { const { value: { uncheck, getNode } @@ -337,7 +350,11 @@ export default defineComponent({ }) doUpdateValue( checkedKeys, - checkedKeys.map((checkedKey) => getNode(checkedKey)?.rawNode || null) + checkedKeys.map((checkedKey) => getNode(checkedKey)?.rawNode || null), + checkedKeys.map( + (checkedKey) => + getPathValues(getNode(checkedKey), valueField) || null + ) ) } } @@ -617,9 +634,9 @@ export default defineComponent({ function handleClear (e: MouseEvent): void { e.stopPropagation() if (props.multiple) { - doUpdateValue([], []) + doUpdateValue([], [], []) } else { - doUpdateValue(null, null) + doUpdateValue(null, null, null) } } function handleTriggerFocus (e: FocusEvent): void { @@ -678,7 +695,7 @@ export default defineComponent({ if (multiple && Array.isArray(mergedValue)) { doUncheck((option as any)[valueField]) } else { - doUpdateValue(null, null) + doUpdateValue(null, null, null) } } function handleKeyDown (e: KeyboardEvent): void { diff --git a/src/cascader/src/utils.ts b/src/cascader/src/utils.ts index 5ca4800c703..25ea9fe7dae 100644 --- a/src/cascader/src/utils.ts +++ b/src/cascader/src/utils.ts @@ -1,5 +1,6 @@ import type { TmNode, CascaderOption } from './interface' import type { SelectBaseOption } from '../../select/src/interface' +import { Key } from './interface' function traverseWithCallback ( options: T[], @@ -57,4 +58,18 @@ function getPathLabel ( return path.reverse().join(separator) } -export { traverseWithCallback, createSelectOptions, getPathLabel } +function getPathValues (node: TmNode | null, valueField: string): Key[] { + const pathNode: Key[] = [] + while (node) { + pathNode.push((node.rawNode as any)[valueField]) + node = node.parent + } + return pathNode.reverse() +} + +export { + traverseWithCallback, + createSelectOptions, + getPathLabel, + getPathValues +} From 2101a1992cd73eb091236abe7996fa8189475b66 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 9 Oct 2021 09:03:05 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E8=8A=82=E7=82=B9=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cascader/src/Cascader.tsx | 40 ++++++++++++++++++++--------------- src/cascader/src/utils.ts | 17 +-------------- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/cascader/src/Cascader.tsx b/src/cascader/src/Cascader.tsx index 33688192c1b..be7fd446734 100644 --- a/src/cascader/src/Cascader.tsx +++ b/src/cascader/src/Cascader.tsx @@ -29,7 +29,7 @@ import { call, useAdjustedTo, warnOnce } from '../../_utils' import type { ExtractPublicPropTypes, MaybeArray } from '../../_utils' import { cascaderLight } from '../styles' import type { CascaderTheme } from '../styles' -import { getPathLabel, getPathValues } from './utils' +import { getPathLabel } from './utils' import CascaderMenu from './CascaderMenu' import CascaderSelectMenu from './CascaderSelectMenu' import { @@ -256,7 +256,10 @@ export default defineComponent({ function doUpdateValue ( value: Value | null, option: CascaderOption | null | Array, - pathValues: null | Array | Array> + optionPath: + | null + | Array + | Array> ): void { const { onUpdateValue, @@ -264,11 +267,15 @@ export default defineComponent({ onChange } = props const { nTriggerFormInput, nTriggerFormChange } = formItem - if (onUpdateValue) { call(onUpdateValue as OnUpdateValueImpl, value, option, pathValues) } + if (onUpdateValue) { + call(onUpdateValue as OnUpdateValueImpl, value, option, optionPath) + } if (_onUpdateValue) { - call(_onUpdateValue as OnUpdateValueImpl, value, option, pathValues) + call(_onUpdateValue as OnUpdateValueImpl, value, option, optionPath) + } + if (onChange) { + call(onChange as OnUpdateValueImpl, value, option, optionPath) } - if (onChange) { call(onChange as OnUpdateValueImpl, value, option, pathValues) } uncontrolledValueRef.value = value nTriggerFormInput() nTriggerFormChange() @@ -280,9 +287,9 @@ export default defineComponent({ hoverKeyRef.value = key } function doCheck (key: Key): boolean { - const { cascade, multiple, filterable, valueField } = props + const { cascade, multiple, filterable } = props const { - value: { check, getNode } + value: { check, getNode, getPath } } = treeMateRef if (multiple) { try { @@ -295,9 +302,8 @@ export default defineComponent({ checkedKeys.map( (checkedKey) => getNode(checkedKey)?.rawNode || null ), - checkedKeys.map( - (checkedKey) => - getPathValues(getNode(checkedKey), valueField) || null + checkedKeys.map((checkedKey) => + getPath(checkedKey).treeNodePath.map((v) => v.rawNode) ) ) if (filterable) focusSelectionInput() @@ -318,11 +324,12 @@ export default defineComponent({ } else { if (mergedCheckStrategyRef.value === 'child') { const tmNode = getNode(key) + console.log('%%%%%%', getPath(key)) if (tmNode?.isLeaf) { doUpdateValue( key, tmNode.rawNode, - getPathValues(tmNode, valueField) + getPath(key).treeNodePath.map((v) => v.rawNode) ) } else { return false @@ -332,17 +339,17 @@ export default defineComponent({ doUpdateValue( key, tmNode?.rawNode || null, - getPathValues(tmNode, valueField) + getPath(key).treeNodePath.map((v) => v.rawNode) ) } } return true } function doUncheck (key: Key): void { - const { cascade, multiple, valueField } = props + const { cascade, multiple } = props if (multiple) { const { - value: { uncheck, getNode } + value: { uncheck, getNode, getPath } } = treeMateRef const { checkedKeys } = uncheck(key, mergedKeysRef.value.checkedKeys, { cascade, @@ -351,9 +358,8 @@ export default defineComponent({ doUpdateValue( checkedKeys, checkedKeys.map((checkedKey) => getNode(checkedKey)?.rawNode || null), - checkedKeys.map( - (checkedKey) => - getPathValues(getNode(checkedKey), valueField) || null + checkedKeys.map((checkedKey) => + getPath(checkedKey).treeNodePath.map((v) => v.rawNode) ) ) } diff --git a/src/cascader/src/utils.ts b/src/cascader/src/utils.ts index 25ea9fe7dae..5ca4800c703 100644 --- a/src/cascader/src/utils.ts +++ b/src/cascader/src/utils.ts @@ -1,6 +1,5 @@ import type { TmNode, CascaderOption } from './interface' import type { SelectBaseOption } from '../../select/src/interface' -import { Key } from './interface' function traverseWithCallback ( options: T[], @@ -58,18 +57,4 @@ function getPathLabel ( return path.reverse().join(separator) } -function getPathValues (node: TmNode | null, valueField: string): Key[] { - const pathNode: Key[] = [] - while (node) { - pathNode.push((node.rawNode as any)[valueField]) - node = node.parent - } - return pathNode.reverse() -} - -export { - traverseWithCallback, - createSelectOptions, - getPathLabel, - getPathValues -} +export { traverseWithCallback, createSelectOptions, getPathLabel } From c879df7ce63c4d0e19b551dbbec9047e51256f62 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 9 Oct 2021 14:00:46 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E8=80=83=E8=99=91=E8=8A=82=E7=82=B9?= =?UTF-8?q?null=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cascader/src/Cascader.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cascader/src/Cascader.tsx b/src/cascader/src/Cascader.tsx index be7fd446734..25901ce17fe 100644 --- a/src/cascader/src/Cascader.tsx +++ b/src/cascader/src/Cascader.tsx @@ -302,8 +302,9 @@ export default defineComponent({ checkedKeys.map( (checkedKey) => getNode(checkedKey)?.rawNode || null ), - checkedKeys.map((checkedKey) => - getPath(checkedKey).treeNodePath.map((v) => v.rawNode) + checkedKeys.map( + (checkedKey) => + getPath(checkedKey)?.treeNodePath?.map((v) => v.rawNode) || null ) ) if (filterable) focusSelectionInput() @@ -324,7 +325,6 @@ export default defineComponent({ } else { if (mergedCheckStrategyRef.value === 'child') { const tmNode = getNode(key) - console.log('%%%%%%', getPath(key)) if (tmNode?.isLeaf) { doUpdateValue( key, @@ -339,7 +339,7 @@ export default defineComponent({ doUpdateValue( key, tmNode?.rawNode || null, - getPath(key).treeNodePath.map((v) => v.rawNode) + getPath(key)?.treeNodePath?.map((v) => v.rawNode) || null ) } } @@ -358,8 +358,9 @@ export default defineComponent({ doUpdateValue( checkedKeys, checkedKeys.map((checkedKey) => getNode(checkedKey)?.rawNode || null), - checkedKeys.map((checkedKey) => - getPath(checkedKey).treeNodePath.map((v) => v.rawNode) + checkedKeys.map( + (checkedKey) => + getPath(checkedKey)?.treeNodePath?.map((v) => v.rawNode) || null ) ) }