From addfcc0634dbab23a41d4867b9cebb0abbe00fc3 Mon Sep 17 00:00:00 2001 From: Lyca Date: Thu, 10 Mar 2022 23:29:57 +0800 Subject: [PATCH] feat(next/antd): support search in readPretty, fix rowClick in readPretty, fix search selected bug (#2920) --- packages/antd/src/select-table/index.tsx | 57 +++++++++------ .../src/select-table/useFilterOptions.tsx | 8 ++- .../antd/src/select-table/useTitleAddon.tsx | 71 +++++++++++++++++++ packages/next/src/select-table/index.tsx | 49 +++++++------ .../src/select-table/useFilterOptions.tsx | 9 ++- .../next/src/select-table/useTitleAddon.tsx | 31 +++++--- 6 files changed, 164 insertions(+), 61 deletions(-) create mode 100644 packages/antd/src/select-table/useTitleAddon.tsx diff --git a/packages/antd/src/select-table/index.tsx b/packages/antd/src/select-table/index.tsx index b4fb0c6dca1..b52828f7687 100644 --- a/packages/antd/src/select-table/index.tsx +++ b/packages/antd/src/select-table/index.tsx @@ -8,6 +8,7 @@ import { SearchProps } from 'antd/lib/input' import { useFilterOptions } from './useFilterOptions' import { useFlatOptions } from './useFlatOptions' import { useSize } from './useSize' +import { useTitleAddon } from './useTitleAddon' import { useCheckSlackly } from './useCheckSlackly' import { getUISelected, getOutputData } from './utils' import { usePrefixCls } from '../__builtins__' @@ -115,19 +116,6 @@ export const SelectTable: ComposedSelectTable = observer((props) => { dataSource = isFn(rowKey) ? addPrimaryKey(dataSource, rowKey, primaryKey) : dataSource - const flatDataSource = useFlatOptions(dataSource) - - // selected keys for Table UI - const selected = getUISelected( - value, - flatDataSource, - primaryKey, - valueType, - optionAsValue, - mode, - rowSelection?.checkStrictly, - rowKey - ) // Filter dataSource By Search const filteredDataSource = useFilterOptions( @@ -144,13 +132,25 @@ export const SelectTable: ComposedSelectTable = observer((props) => { return [...filteredDataSource].sort((a, b) => filterSort(a, b)) }, [filteredDataSource, filterSort]) + const flatDataSource = useFlatOptions(dataSource) + + // selected keys for Table UI + const selected = getUISelected( + value, + flatDataSource, + primaryKey, + valueType, + optionAsValue, + mode, + rowSelection?.checkStrictly, + rowKey + ) + // readPretty Value - const readPrettyDataSource = useMemo( - () => - orderedFilteredDataSource?.filter((item) => - selected?.includes(item?.[primaryKey]) - ), - [orderedFilteredDataSource, selected, primaryKey] + const readPrettyDataSource = useFilterOptions( + orderedFilteredDataSource, + selected, + (value, item) => value.includes(item[primaryKey]) ) const onInnerSearch = (searchText) => { @@ -177,7 +177,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } const onRowClick = (record) => { - if (disabled || readOnly || record?.disabled) { + if (readPretty || disabled || readOnly || record?.disabled) { return } const selectedRowKey = record?.[primaryKey] @@ -204,7 +204,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } } - // Antd TreeData SlacklyChange for onRowClick + // TreeData SlacklyChange const onSlacklyChange = (currentSelected: any[]) => { let { selectedRowKeys, records } = useCheckSlackly( currentSelected, @@ -215,12 +215,23 @@ export const SelectTable: ComposedSelectTable = observer((props) => { onInnerChange(selectedRowKeys, records) } + // Table All Checkbox + const titleAddon = useTitleAddon( + selected, + useFlatOptions(filteredDataSource), + primaryKey, + mode, + disabled, + readOnly, + onInnerChange + ) + // Antd rowSelection type const modeAsType: any = { multiple: 'checkbox', single: 'radio' }?.[mode] return (
- {showSearch && !readPretty ? ( + {showSearch ? ( { ? undefined : { ...rowSelection, + ...titleAddon, getCheckboxProps: (record) => ({ ...(rowSelection?.getCheckboxProps?.(record) as any), disabled: disabled || record?.disabled, @@ -281,6 +293,7 @@ SelectTable.Column = TableColumn SelectTable.defaultProps = { showSearch: false, + valueType: 'all', primaryKey: 'key', mode: 'multiple', } diff --git a/packages/antd/src/select-table/useFilterOptions.tsx b/packages/antd/src/select-table/useFilterOptions.tsx index 96b3600043e..3bfe9a51d57 100644 --- a/packages/antd/src/select-table/useFilterOptions.tsx +++ b/packages/antd/src/select-table/useFilterOptions.tsx @@ -12,6 +12,9 @@ function includesOption(option: any, search: string) { const _includesOption = (option: any) => { const keys = Object.keys(option || {}) return keys.some((key) => { + if (key === '__level') { + return false + } const value = option[key] if (React.isValidElement(value)) return false if (key !== 'children' && !searched.has(value)) { @@ -36,17 +39,16 @@ function toArray(value: T | T[]): T[] { const useFilterOptions = ( options: any[], - searchValue?: string, + searchValue?: string | string[], filterOption?: IFilterOption ) => React.useMemo(() => { if (!searchValue || filterOption === false) { return options } - const upperSearch = searchValue.toUpperCase() const filterFunc = isFn(filterOption) ? filterOption - : (_: string, option: any) => includesOption(option, upperSearch) + : (value: any, option: any) => includesOption(option, value.toUpperCase()) const doFilter = (arr: any[]) => { const filterArr: any[] = [] diff --git a/packages/antd/src/select-table/useTitleAddon.tsx b/packages/antd/src/select-table/useTitleAddon.tsx new file mode 100644 index 00000000000..929b890dae2 --- /dev/null +++ b/packages/antd/src/select-table/useTitleAddon.tsx @@ -0,0 +1,71 @@ +import React from 'react' +import { Checkbox } from 'antd' + +// 重写表格表头Checkbox +const newCheckbox = + ( + selected, + filteredFlatDataSource, + primaryKey, + disabled, + readOnly, + onChange + ) => + () => { + const currentDataSource = filteredFlatDataSource.filter( + (item) => !item.disabled + ) + const currentDataSourceKeys = currentDataSource.map( + (item) => item?.[primaryKey] + ) + const currentSelected = selected.filter((item) => + currentDataSourceKeys.includes(item) + ) + const indeterminate = !!( + currentSelected?.length && + currentSelected.length !== currentDataSource.length + ) + return ( + { + if (!readOnly) { + if (e.target.checked || indeterminate) { + onChange?.(currentDataSourceKeys, currentDataSource) + } else { + onChange?.([], []) + } + } + }} + /> + ) + } + +const useTitleAddon = ( + selected: any[], + filteredFlatDataSource: any[], + primaryKey: string, + mode: string, + disabled: boolean, + readOnly: boolean, + onChange: (selectedRowKeys: any[], record: any[]) => any +) => { + if (mode === 'single') { + return {} + } + return { + columnTitle: newCheckbox( + selected, + filteredFlatDataSource, + primaryKey, + disabled, + readOnly, + onChange + ), + } +} + +export { useTitleAddon } diff --git a/packages/next/src/select-table/index.tsx b/packages/next/src/select-table/index.tsx index 8e24b9c9614..d138baf74a8 100644 --- a/packages/next/src/select-table/index.tsx +++ b/packages/next/src/select-table/index.tsx @@ -118,19 +118,6 @@ export const SelectTable: ComposedSelectTable = observer((props) => { dataSource = isFn(rowKey) ? addPrimaryKey(dataSource, rowKey, primaryKey) : dataSource - const flatDataSource = useFlatOptions(dataSource) - - // selected keys for Table UI - const selected = getUISelected( - value, - flatDataSource, - primaryKey, - valueType, - optionAsValue, - mode, - rowSelection?.checkStrictly, - rowKey - ) // Filter dataSource By Search const filteredDataSource = useFilterOptions( @@ -147,13 +134,25 @@ export const SelectTable: ComposedSelectTable = observer((props) => { return [...filteredDataSource].sort((a, b) => filterSort(a, b)) }, [filteredDataSource, filterSort]) + const flatDataSource = useFlatOptions(dataSource) + + // selected keys for Table UI + const selected = getUISelected( + value, + flatDataSource, + primaryKey, + valueType, + optionAsValue, + mode, + rowSelection?.checkStrictly, + rowKey + ) + // readPretty Value - const readPrettyDataSource = useMemo( - () => - orderedFilteredDataSource?.filter((item) => - selected?.includes(item?.[primaryKey]) - ), - [orderedFilteredDataSource, selected, primaryKey] + const readPrettyDataSource = useFilterOptions( + orderedFilteredDataSource, + selected, + (value, item) => value.includes(item[primaryKey]) ) const onInnerSearch = (searchText) => { @@ -180,7 +179,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } const onRowClick = (record) => { - if (disabled || readOnly || record?.disabled) { + if (readPretty || disabled || readOnly || record?.disabled) { return } const selectedRowKey = record?.[primaryKey] @@ -207,7 +206,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } } - // Fusion TreeData SlacklyChange + // TreeData SlacklyChange const onSlacklyChange = (currentSelected: any[]) => { let { selectedRowKeys, records } = useCheckSlackly( currentSelected, @@ -218,10 +217,10 @@ export const SelectTable: ComposedSelectTable = observer((props) => { onInnerChange(selectedRowKeys, records) } - // Fusion Table Checkbox + // Table All Checkbox const titleAddon = useTitleAddon( selected, - flatDataSource, + useFlatOptions(filteredDataSource), primaryKey, mode, disabled, @@ -231,7 +230,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { return (
- {showSearch && !readPretty ? ( + {showSearch ? ( { ? undefined : { ...rowSelection, + ...titleAddon, getProps: (record, index) => ({ ...(rowSelection?.getProps?.(record, index) as any), indeterminate: getIndeterminate(record, selected, primaryKey), // 父子关联模式indeterminate值 @@ -266,7 +266,6 @@ export const SelectTable: ComposedSelectTable = observer((props) => { ? onInnerChange : onSlacklyChange, mode, - ...titleAddon, } } columns={props.columns || columns} diff --git a/packages/next/src/select-table/useFilterOptions.tsx b/packages/next/src/select-table/useFilterOptions.tsx index 3da0eddcb3b..3bfe9a51d57 100644 --- a/packages/next/src/select-table/useFilterOptions.tsx +++ b/packages/next/src/select-table/useFilterOptions.tsx @@ -12,6 +12,9 @@ function includesOption(option: any, search: string) { const _includesOption = (option: any) => { const keys = Object.keys(option || {}) return keys.some((key) => { + if (key === '__level') { + return false + } const value = option[key] if (React.isValidElement(value)) return false if (key !== 'children' && !searched.has(value)) { @@ -21,6 +24,7 @@ function includesOption(option: any, search: string) { } return includes(value, search) } + return false }) } return _includesOption(option) @@ -35,17 +39,16 @@ function toArray(value: T | T[]): T[] { const useFilterOptions = ( options: any[], - searchValue?: string, + searchValue?: string | string[], filterOption?: IFilterOption ) => React.useMemo(() => { if (!searchValue || filterOption === false) { return options } - const upperSearch = searchValue.toUpperCase() const filterFunc = isFn(filterOption) ? filterOption - : (_: string, option: any) => includesOption(option, upperSearch) + : (value: any, option: any) => includesOption(option, value.toUpperCase()) const doFilter = (arr: any[]) => { const filterArr: any[] = [] diff --git a/packages/next/src/select-table/useTitleAddon.tsx b/packages/next/src/select-table/useTitleAddon.tsx index a7cbf41b65f..9fb911e4653 100644 --- a/packages/next/src/select-table/useTitleAddon.tsx +++ b/packages/next/src/select-table/useTitleAddon.tsx @@ -3,23 +3,38 @@ import { Checkbox } from '@alifd/next' // 重写表格表头Checkbox const newCheckbox = - (selected, flatDataSource, primaryKey, disabled, readOnly, onChange) => + ( + selected, + filteredFlatDataSource, + primaryKey, + disabled, + readOnly, + onChange + ) => () => { - const allDataSource = flatDataSource.filter((item) => !item.disabled) - const allDataSourceKeys = allDataSource.map((item) => item?.[primaryKey]) + const currentDataSource = filteredFlatDataSource.filter( + (item) => !item.disabled + ) + const currentDataSourceKeys = currentDataSource.map( + (item) => item?.[primaryKey] + ) + const currentSelected = selected.filter((item) => + currentDataSourceKeys.includes(item) + ) const indeterminate = !!( - selected?.length && selected.length !== allDataSourceKeys.length + currentSelected?.length && + currentSelected.length !== currentDataSource.length ) return ( { if (!readOnly) { if (checked || indeterminate) { - onChange?.(allDataSourceKeys, allDataSource) + onChange?.(currentDataSourceKeys, currentDataSource) } else { onChange?.([], []) } @@ -31,7 +46,7 @@ const newCheckbox = const useTitleAddon = ( selected: any[], - flatDataSource: any[], + filteredFlatDataSource: any[], primaryKey: string, mode: string, disabled: boolean, @@ -47,7 +62,7 @@ const useTitleAddon = ( }), titleAddons: newCheckbox( selected, - flatDataSource, + filteredFlatDataSource, primaryKey, disabled, readOnly,