Skip to content

Commit

Permalink
feat(next/antd): fix selected bug3 by search in SelectTable (#2927)
Browse files Browse the repository at this point in the history
* fix(next): fix selected bug2 by search in SelectTable

* feat(next/antd): fix selected bug3 by search in SelectTable
  • Loading branch information
ifblooms authored Mar 12, 2022
1 parent 72534b4 commit bc943de
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 81 deletions.
59 changes: 44 additions & 15 deletions packages/antd/src/select-table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useFilterOptions } from './useFilterOptions'
import { useFlatOptions } from './useFlatOptions'
import { useSize } from './useSize'
import { useTitleAddon } from './useTitleAddon'
import { useCheckSlackly } from './useCheckSlackly'
import { useCheckSlackly, getIndeterminate } from './useCheckSlackly'
import { getUISelected, getOutputData } from './utils'
import { usePrefixCls } from '../__builtins__'

Expand Down Expand Up @@ -121,7 +121,8 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
const filteredDataSource = useFilterOptions(
dataSource,
searchValue,
filterOption
filterOption,
rowSelection?.checkStrictly
)

// Order dataSource By filterSort
Expand All @@ -133,6 +134,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
}, [filteredDataSource, filterSort])

const flatDataSource = useFlatOptions(dataSource)
const flatFilteredDataSource = useFlatOptions(filteredDataSource)

// selected keys for Table UI
const selected = getUISelected(
Expand All @@ -159,20 +161,25 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
onSearch?.(formatted)
}

const onInnerChange = (selectedRowKeys: any[], records: any[]) => {
const onInnerChange = (selectedRowKeys: any[]) => {
if (readOnly) {
return
}
// 筛选后onChange默认的records数据不完整,此处需使用完整数据过滤
const wholeRecords = flatDataSource.filter((item) =>
selectedRowKeys.includes(item?.[primaryKey])
)
const { outputValue, outputOptions } = getOutputData(
selectedRowKeys,
records,
wholeRecords,
dataSource,
primaryKey,
valueType,
optionAsValue,
mode,
rowSelection?.checkStrictly
)

onChange?.(outputValue, outputOptions)
}

Expand All @@ -183,46 +190,45 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
const selectedRowKey = record?.[primaryKey]
const isSelected = selected?.includes(selectedRowKey)
let selectedRowKeys = []
let records = []
if (mode === 'single') {
selectedRowKeys = [selectedRowKey]
records = [record]
} else {
if (isSelected) {
selectedRowKeys = selected.filter((item) => item !== selectedRowKey)
} else {
selectedRowKeys = [...selected, selectedRowKey]
}
records = flatDataSource.filter((item) =>
selectedRowKeys.includes(item?.[primaryKey])
)
}
if (rowSelection?.checkStrictly !== false) {
onInnerChange(selectedRowKeys, records)
onInnerChange(selectedRowKeys)
} else {
onSlacklyChange(selectedRowKeys)
}
}

// TreeData SlacklyChange
const onSlacklyChange = (currentSelected: any[]) => {
let { selectedRowKeys, records } = useCheckSlackly(
let { selectedRowKeys } = useCheckSlackly(
currentSelected,
selected,
flatDataSource,
flatFilteredDataSource,
primaryKey,
flatDataSource
rowSelection?.checkStrictly
)
onInnerChange(selectedRowKeys, records)
onInnerChange(selectedRowKeys)
}

// Table All Checkbox
const titleAddon = useTitleAddon(
selected,
useFlatOptions(filteredDataSource),
flatDataSource,
flatFilteredDataSource,
primaryKey,
mode,
disabled,
readOnly,
rowSelection?.checkStrictly,
onInnerChange
)

Expand Down Expand Up @@ -260,9 +266,32 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
...(rowSelection?.getCheckboxProps?.(record) as any),
disabled: disabled || record?.disabled,
}), // antd
...(rowSelection?.checkStrictly !== false
? {}
: {
renderCell: (checked, record, index, originNode) => {
return React.cloneElement(
originNode as React.ReactElement,
{
indeterminate: getIndeterminate(
record,
flatDataSource,
selected,
primaryKey
),
}
)
},
}),
selectedRowKeys: selected,
onChange: onInnerChange,
// onChange: onInnerChange,
onChange:
rowSelection?.checkStrictly !== false
? onInnerChange
: onSlacklyChange,
type: modeAsType,
preserveSelectedRowKeys: true,
checkStrictly: true,
}
}
columns={props.columns || columns}
Expand Down
85 changes: 54 additions & 31 deletions packages/antd/src/select-table/useCheckSlackly.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,91 @@
import { getTreeKeys, hasSelectedKey, completedKeys } from './utils'
import {
getTreeKeys,
hasSelectedKey,
completedKeys,
getCompatibleAllSelected,
} from './utils'

/**
* 判断该字段的 indeterminate 属性
* @param record 当前字段
* @param flatDataSource 完整平铺数据
* @param selected 已选中的字段值集合
* @param primaryKey 键名称
* @returns indeterminate 属性值
*/
const getIndeterminate = (record: any, selected: any[], primaryKey: string) => {
const getIndeterminate = (
record: any,
flatDataSource: any,
selected: any[],
primaryKey: string
) => {
if (selected?.includes(record[primaryKey])) {
return undefined
}
return hasSelectedKey(record.children, selected, primaryKey) || undefined
const wholeRecord = flatDataSource.find(
(item) => item[primaryKey] === record[primaryKey]
)
return hasSelectedKey(wholeRecord.children, selected, primaryKey) || undefined
}

interface ICheckSlackly {
(
currentSelected: any[],
allSelected: any[],
selected: any[],
flatDataSource: any[],
flatFilteredDataSource: any[],
primaryKey: string,
flatDataSource: any[]
): {
selectedRowKeys: any[]
records: any[]
}
checkStrictly: boolean
): { selectedRowKeys: any[] }
}

// 父子节点(节点状态按全完整数据计算,节点操作按筛选数据计算)
const useCheckSlackly: ICheckSlackly = (
currentSelected, // onChange 返回的 keys
allSelected, // Table UI 展示的 keys
selected, // Table UI 展示的 keys
flatDataSource,
flatFilteredDataSource,
primaryKey,
flatDataSource
checkStrictly
) => {
const isSelected = currentSelected.length > allSelected.length // 判断是选中还是取消
const currentKey = [...currentSelected, ...allSelected].find(
(key) => !(currentSelected.includes(key) && allSelected.includes(key)) // 当前变化key不同时存在于两个selected
let isSelected = currentSelected.length > selected.length // 判断是选中还是取消

const currentKey = [...currentSelected, ...selected].find(
(key) => !(currentSelected.includes(key) && selected.includes(key)) // 当前变化key不同时存在于两个selected
)
const currentRecords = flatDataSource.find(
// 从过滤后的数据中获取当前record
const currentRecord = flatFilteredDataSource.find(
(item) => item[primaryKey] === currentKey
)
const currentTreeKeys = getTreeKeys([currentRecords], primaryKey)
let newSelectedRowKeys = []
const currentTreeKeys = getTreeKeys(currentRecord.children, primaryKey)

// 在筛选状态下(按钮的indeterminate状态处于异常)需要通过数据对比判断是否处于全选中状态
if (
getCompatibleAllSelected(
selected,
currentRecord.children,
currentTreeKeys,
checkStrictly,
primaryKey
)
) {
isSelected = false
}

let newSelected = []
if (isSelected) {
// 选中当前key及其子keys
newSelectedRowKeys = [...new Set([...allSelected, ...currentTreeKeys])]
newSelected = [...new Set([...selected, currentKey, ...currentTreeKeys])]
} else {
// 移除当前key及其子keys
newSelectedRowKeys = allSelected.filter(
(key) => !currentTreeKeys.includes(key)
newSelected = selected.filter(
(key) => ![currentKey, ...currentTreeKeys].includes(key)
)
}

newSelectedRowKeys = completedKeys(
flatDataSource,
newSelectedRowKeys,
primaryKey
)
newSelected = completedKeys(flatDataSource, newSelected, primaryKey)

return {
selectedRowKeys: newSelectedRowKeys,
records: flatDataSource.filter((item) =>
newSelectedRowKeys.includes(item[primaryKey])
),
}
return { selectedRowKeys: newSelected }
}

export { useCheckSlackly, getIndeterminate }
6 changes: 4 additions & 2 deletions packages/antd/src/select-table/useFilterOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ function toArray<T>(value: T | T[]): T[] {
const useFilterOptions = (
options: any[],
searchValue?: string | string[],
filterOption?: IFilterOption
filterOption?: IFilterOption,
checkStrictly?: boolean
) =>
React.useMemo(() => {
if (!searchValue || filterOption === false) {
Expand All @@ -57,7 +58,8 @@ const useFilterOptions = (
const filterChildren = doFilter(item.children)
if (filterChildren.length) {
filterArr.push({ ...item, children: filterChildren })
} else if (filterFunc(searchValue, item)) {
} else if (filterFunc(searchValue, item) && checkStrictly !== false) {
// 父子关系启用时,没有可用子元素,不添加父元素
filterArr.push({ ...item, children: [] })
}
} else if (filterFunc(searchValue, item)) {
Expand Down
Loading

0 comments on commit bc943de

Please sign in to comment.