From dfeec96d5a252c9437b4b4ad48f249b403655bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=91=E9=9B=A8?= Date: Wed, 9 Mar 2022 18:03:02 +0800 Subject: [PATCH 1/2] feat: add showCheckedStrategy --- src/Cascader.tsx | 23 ++++++++++++++++++--- src/utils/treeUtil.ts | 24 ++++++++++++++++++++-- tests/index.spec.tsx | 48 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/Cascader.tsx b/src/Cascader.tsx index 272cd142..832539d5 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -43,6 +43,7 @@ export interface InternalFieldNames extends Required { export type SingleValueType = (string | number)[]; export type ValueType = SingleValueType | SingleValueType[]; +export type ShowCheckedStrategy = 'parent' | 'child'; export interface BaseOptionType { disabled?: boolean; @@ -71,6 +72,7 @@ interface BaseCascaderProps React.ReactNode; checkable?: boolean | React.ReactNode; + showCheckedStrategy?: ShowCheckedStrategy; // Search showSearch?: boolean | ShowSearchType; @@ -209,6 +211,7 @@ const Cascader = React.forwardRef((props, re // Children children, dropdownMatchSelectWidth = false, + showCheckedStrategy = 'parent', ...restProps } = props; @@ -296,10 +299,20 @@ const Cascader = React.forwardRef((props, re const deDuplicatedValues = React.useMemo(() => { const checkedKeys = toPathKeys(checkedValues); - const deduplicateKeys = formatStrategyValues(checkedKeys, getPathKeyEntities); + const deduplicateKeys = formatStrategyValues( + checkedKeys, + getPathKeyEntities, + showCheckedStrategy, + ); return [...missingCheckedValues, ...getValueByKeyPath(deduplicateKeys)]; - }, [checkedValues, getPathKeyEntities, getValueByKeyPath, missingCheckedValues]); + }, [ + checkedValues, + getPathKeyEntities, + getValueByKeyPath, + missingCheckedValues, + showCheckedStrategy, + ]); const displayValues = useDisplayValues( deDuplicatedValues, @@ -374,7 +387,11 @@ const Cascader = React.forwardRef((props, re } // Roll up to parent level keys - const deDuplicatedKeys = formatStrategyValues(checkedKeys, getPathKeyEntities); + const deDuplicatedKeys = formatStrategyValues( + checkedKeys, + getPathKeyEntities, + showCheckedStrategy, + ); nextCheckedValues = getValueByKeyPath(deDuplicatedKeys); } diff --git a/src/utils/treeUtil.ts b/src/utils/treeUtil.ts index d67e7e6c..0dca8468 100644 --- a/src/utils/treeUtil.ts +++ b/src/utils/treeUtil.ts @@ -1,10 +1,30 @@ -import type { SingleValueType, DefaultOptionType, InternalFieldNames } from '../Cascader'; +import type { + SingleValueType, + DefaultOptionType, + InternalFieldNames, + ShowCheckedStrategy, +} from '../Cascader'; import type { GetEntities } from '../hooks/useEntities'; -export function formatStrategyValues(pathKeys: React.Key[], getKeyPathEntities: GetEntities) { +export function formatStrategyValues( + pathKeys: React.Key[], + getKeyPathEntities: GetEntities, + showCheckedStrategy: ShowCheckedStrategy, +) { const valueSet = new Set(pathKeys); const keyPathEntities = getKeyPathEntities(); + if (showCheckedStrategy === 'child') { + return pathKeys.filter(key => { + const entity = keyPathEntities[key]; + const children = entity ? entity.children : null; + if (children && children.find(child => child.key && valueSet.has(child.key))) { + return false; + } + return true; + }); + } + return pathKeys.filter(key => { const entity = keyPathEntities[key]; const parent = entity ? entity.parent : null; diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index d1525ab2..06e030db 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -87,6 +87,54 @@ describe('Cascader.Basic', () => { expect(selectedValue.join(',')).toBe('fj,fuzhou,mawei'); }); + it('should support showCheckedStrategy parent', () => { + const wrapper = mount( + + + , + ); + wrapper.find('input').simulate('click'); + let menus = wrapper.find('.rc-cascader-menu'); + expect(menus.length).toBe(1); + wrapper.clickOption(0, 2); + menus = wrapper.find('.rc-cascader-menu'); + expect(menus.length).toBe(2); + wrapper.clickOption(1, 0); + wrapper.clickOption(1, 1); + expect(selectedValue.join(',')).toBe('bj'); + }); + + it('should support showCheckedStrategy child', () => { + const wrapper = mount( + + + , + ); + wrapper.find('input').simulate('click'); + + // Menu 1 + let menus = wrapper.find('.rc-cascader-menu'); + expect(menus.length).toBe(1); + wrapper.clickOption(0, 2); + menus = wrapper.find('.rc-cascader-menu'); + expect(menus.length).toBe(2); + wrapper.clickOption(1, 0); + wrapper.clickOption(1, 1); + expect(selectedValue.join(',')).toBe('bj,chaoyang,bj,haidian'); + }); + it('should has defaultValue', () => { const wrapper = mount( Date: Thu, 10 Mar 2022 14:20:18 +0800 Subject: [PATCH 2/2] feat: update variable --- src/Cascader.tsx | 7 ++++--- src/utils/commonUtil.ts | 2 ++ src/utils/treeUtil.ts | 20 +++++--------------- tests/index.spec.tsx | 6 ++++-- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/Cascader.tsx b/src/Cascader.tsx index 832539d5..96575719 100644 --- a/src/Cascader.tsx +++ b/src/Cascader.tsx @@ -7,7 +7,8 @@ import type { BaseSelectRef, BaseSelectPropsWithoutPrivate, BaseSelectProps } fr import { BaseSelect } from 'rc-select'; import OptionList from './OptionList'; import CascaderContext from './context'; -import { fillFieldNames, toPathKey, toPathKeys } from './utils/commonUtil'; +import type { SHOW_CHILD } from './utils/commonUtil'; +import { fillFieldNames, toPathKey, toPathKeys, SHOW_PARENT } from './utils/commonUtil'; import useDisplayValues from './hooks/useDisplayValues'; import useRefFunc from './hooks/useRefFunc'; import useEntities from './hooks/useEntities'; @@ -43,7 +44,7 @@ export interface InternalFieldNames extends Required { export type SingleValueType = (string | number)[]; export type ValueType = SingleValueType | SingleValueType[]; -export type ShowCheckedStrategy = 'parent' | 'child'; +export type ShowCheckedStrategy = typeof SHOW_PARENT | typeof SHOW_CHILD; export interface BaseOptionType { disabled?: boolean; @@ -211,7 +212,7 @@ const Cascader = React.forwardRef((props, re // Children children, dropdownMatchSelectWidth = false, - showCheckedStrategy = 'parent', + showCheckedStrategy = SHOW_PARENT, ...restProps } = props; diff --git a/src/utils/commonUtil.ts b/src/utils/commonUtil.ts index bd1289d4..59562678 100644 --- a/src/utils/commonUtil.ts +++ b/src/utils/commonUtil.ts @@ -6,6 +6,8 @@ import type { } from '../Cascader'; export const VALUE_SPLIT = '__RC_CASCADER_SPLIT__'; +export const SHOW_PARENT = 'SHOW_PARENT'; +export const SHOW_CHILD = 'SHOW_CHILD'; export function toPathKey(value: SingleValueType) { return value.join(VALUE_SPLIT); diff --git a/src/utils/treeUtil.ts b/src/utils/treeUtil.ts index 0dca8468..0b143e65 100644 --- a/src/utils/treeUtil.ts +++ b/src/utils/treeUtil.ts @@ -5,6 +5,7 @@ import type { ShowCheckedStrategy, } from '../Cascader'; import type { GetEntities } from '../hooks/useEntities'; +import { SHOW_CHILD } from './commonUtil'; export function formatStrategyValues( pathKeys: React.Key[], @@ -14,25 +15,14 @@ export function formatStrategyValues( const valueSet = new Set(pathKeys); const keyPathEntities = getKeyPathEntities(); - if (showCheckedStrategy === 'child') { - return pathKeys.filter(key => { - const entity = keyPathEntities[key]; - const children = entity ? entity.children : null; - if (children && children.find(child => child.key && valueSet.has(child.key))) { - return false; - } - return true; - }); - } - return pathKeys.filter(key => { const entity = keyPathEntities[key]; const parent = entity ? entity.parent : null; + const children = entity ? entity.children : null; - if (parent && !parent.node.disabled && valueSet.has(parent.key)) { - return false; - } - return true; + return showCheckedStrategy === SHOW_CHILD + ? !(children && children.some(child => child.key && valueSet.has(child.key))) + : !(parent && !parent.node.disabled && valueSet.has(parent.key)); }); } diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 06e030db..904bf9fa 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -94,7 +94,7 @@ describe('Cascader.Basic', () => { changeOnSelect options={addressOptions} onChange={onChange} - showCheckedStrategy={'parent'} + showCheckedStrategy={'SHOW_PARENT'} > , @@ -117,7 +117,7 @@ describe('Cascader.Basic', () => { changeOnSelect options={addressOptions} onChange={onChange} - showCheckedStrategy={'child'} + showCheckedStrategy={'SHOW_CHILD'} > , @@ -132,6 +132,8 @@ describe('Cascader.Basic', () => { expect(menus.length).toBe(2); wrapper.clickOption(1, 0); wrapper.clickOption(1, 1); + expect(selectedValue[0].join(',')).toBe('bj,chaoyang'); + expect(selectedValue[1].join(',')).toBe('bj,haidian'); expect(selectedValue.join(',')).toBe('bj,chaoyang,bj,haidian'); });