Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(next/antd): fix selected bug3 by search in SelectTable #2927

Merged
merged 5 commits into from
Mar 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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