Skip to content

Commit

Permalink
fix(next): fix selected bug2 by search in SelectTable (#2924)
Browse files Browse the repository at this point in the history
  • Loading branch information
ifblooms authored Mar 11, 2022
1 parent c672601 commit 6e9a8ae
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 80 deletions.
37 changes: 23 additions & 14 deletions packages/next/src/select-table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
const filteredDataSource = useFilterOptions(
dataSource,
searchValue,
filterOption
filterOption,
rowSelection?.checkStrictly
)

// Order dataSource By filterSort
Expand Down Expand Up @@ -162,20 +163,26 @@ 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 @@ -186,37 +193,33 @@ 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,
primaryKey,
flatDataSource,
flatFilteredDataSource
flatFilteredDataSource,
primaryKey,
rowSelection?.checkStrictly
)
onInnerChange(selectedRowKeys, records)
onInnerChange(selectedRowKeys)
}

// Table All Checkbox
Expand All @@ -228,6 +231,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
mode,
disabled,
readOnly,
rowSelection?.checkStrictly,
onInnerChange
)

Expand Down Expand Up @@ -260,7 +264,12 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
...titleAddon,
getProps: (record, index) => ({
...(rowSelection?.getProps?.(record, index) as any),
indeterminate: getIndeterminate(record, selected, primaryKey), // 父子关联模式indeterminate值
indeterminate: getIndeterminate(
record,
flatDataSource,
selected,
primaryKey
), // 父子关联模式indeterminate值
disabled: disabled || record?.disabled,
}), // fusion
selectedRowKeys: selected,
Expand Down
83 changes: 51 additions & 32 deletions packages/next/src/select-table/useCheckSlackly.tsx
Original file line number Diff line number Diff line change
@@ -1,72 +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[],
primaryKey: string,
selected: any[],
flatDataSource: any[],
flatFilteredDataSource: any[]
): {
selectedRowKeys: any[]
records: any[]
}
flatFilteredDataSource: any[],
primaryKey: string,
checkStrictly: boolean
): { selectedRowKeys: any[] }
}

// 父子节点(节点状态按全完整数据计算,节点操作按筛选数据计算)
const useCheckSlackly: ICheckSlackly = (
currentSelected, // onChange 返回的 keys
allSelected, // Table UI 展示的 keys
primaryKey,
selected, // Table UI 展示的 keys
flatDataSource,
flatFilteredDataSource
flatFilteredDataSource,
primaryKey,
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
)
// 从过滤后的数据中获取当前record
const currentRecord = flatFilteredDataSource.find(
(item) => item[primaryKey] === currentKey
)
const currentTreeKeys = getTreeKeys([currentRecord], 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/next/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
72 changes: 41 additions & 31 deletions packages/next/src/select-table/useTitleAddon.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,20 @@
import React from 'react'
import { Checkbox } from '@alifd/next'
import { completedKeys, getCompatibleAllSelected } from './utils'

// 重写表格表头Checkbox(节点状态按全完整数据计算,节点操作按筛选数据计算)
const newCheckbox =
(
selected,
flatDataSource,
filteredFlatDataSource,
flatFilteredDataSource,
primaryKey,
disabled,
readOnly,
checkStrictly,
onChange
) =>
() => {
// 当前可全选的keys
const currentSelected = filteredFlatDataSource
.filter((item) => !item.disabled)
.map((item) => item?.[primaryKey])

// 点击全选的完整数据(筛选前后)
const newSelected = [...new Set([...selected, ...currentSelected])]
const newRecords = flatDataSource.filter((item) =>
newSelected.includes(item[primaryKey])
)

// 取消全选的剩余数据(筛选前后)
const restSelected = selected.filter(
(key) => !currentSelected.includes(key)
)
const restRecords = flatDataSource.filter((item) =>
restSelected.includes(item[primaryKey])
)

// 全选框是否选中
const checked = Boolean(
selected?.length &&
Expand All @@ -41,33 +24,59 @@ const newCheckbox =
// 全选框是否未完全选中
const indeterminate = Boolean(selected?.length && !checked)

const onInnerChange = (checked) => {
if (!readOnly) {
let isSelected = checked
// 当前可执行全选的keys
const usableKeys = flatFilteredDataSource
.filter((item) => !item.disabled)
.map((item) => item?.[primaryKey])
// 在筛选状态下(按钮的indeterminate状态处于异常)需要通过数据对比判断是否处于全选中状态
if (
getCompatibleAllSelected(
selected,
flatFilteredDataSource,
usableKeys,
checkStrictly,
primaryKey
)
) {
isSelected = false
}

let newSelected = []
if (isSelected) {
// 执行全选
newSelected = [...new Set([...selected, ...usableKeys])]
} else {
// 执行取消全选
newSelected = selected.filter((key) => !usableKeys.includes(key))
}
newSelected = completedKeys(flatDataSource, newSelected, primaryKey)
onChange?.(newSelected)
}
}

return (
<Checkbox
key="titleAddons"
disabled={disabled}
checked={checked}
indeterminate={indeterminate}
onChange={(checked) => {
if (!readOnly) {
if (checked) {
onChange?.(newSelected, newRecords)
} else {
onChange?.(restSelected, restRecords)
}
}
}}
onChange={onInnerChange}
/>
)
}

const useTitleAddon = (
selected: any[],
flatDataSource: any[],
filteredFlatDataSource: any[],
flatFilteredDataSource: any[],
primaryKey: string,
mode: string,
disabled: boolean,
readOnly: boolean,
checkStrictly: boolean,
onChange: (selectedRowKeys: any[], record: any[]) => any
) => {
if (mode === 'single') {
Expand All @@ -80,10 +89,11 @@ const useTitleAddon = (
titleAddons: newCheckbox(
selected,
flatDataSource,
filteredFlatDataSource,
flatFilteredDataSource,
primaryKey,
disabled,
readOnly,
checkStrictly,
onChange
),
}
Expand Down
Loading

0 comments on commit 6e9a8ae

Please sign in to comment.